#' @title  Extending the multilateral GEKS price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geks_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{geks_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geks_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geks(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geks(data, t0, end., wstart = t0, window)*
              geks(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geks(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geks(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geks(data, tT, t, wstart = tT, window) / geks(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geks(data, th, t, wstart = tT, window) / geks(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geks(data, tm, t, wstart = tT, window) / geks(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geks(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geks(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geks(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral GEKS price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geks_fbew
#' @return This function returns a value of the multilateral GEKS price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{geks_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geks_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geks(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geks_fbmw
#' @return This function returns a value of the multilateral GEKS price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{geks_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geks_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geks_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-W price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-W price index (GEKS based on the Walsh formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksw_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-W price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{geksw_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geksw_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksw(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksw(data, t0, end., wstart = t0, window)*
              geksw(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksw(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksw(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksw(data, tT, t, wstart = tT, window) / geksw(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksw(data, th, t, wstart = tT, window) / geksw(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <- lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksw(data, tm, t, wstart = tT, window) / geksw(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksw(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksw(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksw(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }
  

#' @title  Extending the multilateral GEKS-W price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-W price index (GEKS based on the Walsh formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksw_fbew
#' @return This function returns a value of the multilateral GEKS-W price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Walsh, C. M. (1901). \emph{The Measurement of General Exchange Value}. The MacMillan Company, New York.}
#'
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{geksw_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksw_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksw(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-W price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-W price index (GEKS based on the Walsh formula) extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksw_fbmw
#' @return This function returns a value of the multilateral GEKS-W price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions:  \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Walsh, C. M. (1901). \emph{The Measurement of General Exchange Value}. The MacMillan Company, New York.}
#'
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{geksw_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksw_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksw_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-J price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-J price index (GEKS based on the Jevons formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character). A column \code{quantities} is needed because this function uses unit values as monthly prices.
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksj_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-J price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{geksj_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geksj_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksj(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksj(data, t0, end., wstart = t0, window)*
              geksj(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksj(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksj(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksj(data, tT, t, wstart = tT, window) / geksj(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksj(data, th, t, wstart = tT, window) / geksj(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksj(data, tm, t, wstart = tT, window) / geksj(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksj(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksj(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksj(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }
  

#' @title  Extending the multilateral GEKS-J price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-J price index (i.e. the GEKS price index based on the Jevons formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character). A column \code{quantities} is needed because this function uses unit values as monthly prices.
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksj_fbew
#' @return This function returns a value of the multilateral GEKS-J price index (i.e. the GEKS price index based on the Jevons formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{geksj_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksj_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksj(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-J price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-J price index (i.e. the GEKS price index based on the Jevons formula) extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character). A column \code{quantities} is needed because this function uses unit values as monthly prices.
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksj_fbmw
#' @return This function returns a value of the multilateral GEKS-J price index (i.e. the GEKS price index based on the Jevons formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{geksj_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksj_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksj_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
  
}


#' @title  Extending the multilateral CCDI price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral CCDI price index (GEKS based on the Tornqvist formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname ccdi_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral CCDI price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Caves, D.W., Christensen, L.R. and Diewert, W.E. (1982). \emph{Multilateral comparisons of output, input, and productivity using superlative index numbers.} Economic Journal 92, 73-86.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{ccdi_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

ccdi_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(ccdi(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (ccdi(data, t0, end., wstart = t0, window)*
              ccdi(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, ccdi(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * ccdi(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * ccdi(data, tT, t, wstart = tT, window) / ccdi(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * ccdi(data, th, t, wstart = tT, window) / ccdi(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <- lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * ccdi(data, tm, t, wstart = tT, window) / ccdi(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * ccdi(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * ccdi(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * ccdi(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral CCDI price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral CCDI price index (GEKS based on the Tornqvist formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname ccdi_fbew
#' @return This function returns a value of the multilateral CCDI price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Caves, D.W., Christensen, L.R. and Diewert, W.E. (1982). \emph{Multilateral comparisons of output, input, and productivity using superlative index numbers.} Economic Journal 92, 73-86.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{ccdi_fbew(milk, start="2018-12", end="2019-08")}
#' @export

ccdi_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * ccdi(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral CCDI price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral CCDI price index (GEKS based on the Tornqvist formula) extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname ccdi_fbmw
#' @return This function returns a value of the multilateral CCDI price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Caves, D.W., Christensen, L.R. and Diewert, W.E. (1982). \emph{Multilateral comparisons of output, input, and productivity using superlative index numbers.} Economic Journal 92, 73-86.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{ccdi_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

ccdi_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * ccdi_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral Geary-Khamis price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral Geary-Khamis price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname gk_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral Geary-Khamis price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{gk_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

gk_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(gk(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (gk(data, t0, end., wstart = t0, window)*
              gk(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, gk(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * gk(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(set,
  set[length(set)] * gk(data, tT, t, wstart = tT, window) / gk(data, tT, t1, wstart =
  tT1, window))
  if (splice == "half")
  set <-
  c(set,
  set[length(set)] * gk(data, th, t, wstart = tT, window) / gk(data, th, t1, wstart =
  tT1, window))
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <- lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * gk(data, tm, t, wstart = tT, window) / gk(data, tm, t1, wstart = tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * gk(data, tT, t, wstart = tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * gk(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * gk(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral Geary-Khamis price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral Geary-Khamis price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname gk_fbew
#' @return This function returns a value of the multilateral Geary-Khamis price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Geary, R. G. (1958). \emph{A Note on Comparisons of Exchange Rates and Purchasing Power between Countries.} Journal of the Royal Statistical Society, Series A, 121, 97-99.}
#'
#' {Khamis, S. H. (1970). \emph{Properties and Conditions for the Existence of a new Type of Index Number.} Sankhya Series B32, 81-98.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{gk_fbew(milk, start="2018-12", end="2019-08")}
#' @export

gk_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * gkreal(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral Geary-Khamis price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral Geary-Khamis price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname gk_fbmw
#' @return This function returns a value of the multilateral Geary-Khamis price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions:  \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Geary, R. G. (1958). \emph{A Note on Comparisons of Exchange Rates and Purchasing Power between Countries.} Journal of the Royal Statistical Society, Series A, 121, 97-99.}
#'
#' {Khamis, S. H. (1970). \emph{Properties and Conditions for the Existence of a new Type of Index Number.} Sankhya Series B32, 81-98.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{gk_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

gk_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * gk_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral TPD price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral TPD price index (Time Product Dummy index) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname tpd_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral TPD price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {de  Haan,  J.  and  F.  Krsinich  (2014). \emph{Time  Dummy  Hedonic  and  Quality-Adjusted  Unit Value Indexes: Do They Really Differ?} Paper presented at the Society for Economic Measurement Conference, 18-20 August 2014, Chicago, U.S.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{tpd_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

tpd_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(tpd(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (tpd(data, t0, end., wstart = t0, window)*
              tpd(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, tpd(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * tpd(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * tpd(data, tT, t, wstart = tT, window) / tpd(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * tpd(data, th, t, wstart = tT, window) / tpd(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * tpd(data, tm, t, wstart = tT, window) / tpd(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * tpd(data, tT, t, wstart = tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * tpd(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * tpd(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral TPD price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral TPD price index (Time Product Dummy index) extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname tpd_fbew
#' @return This function returns a value of the multilateral TPD price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).  
#' @references
#' {de  Haan,  J.  and  F.  Krsinich  (2014). \emph{Time  Dummy  Hedonic  and  Quality-Adjusted  Unit Value Indexes: Do They Really Differ?} Paper presented at the Society for Economic Measurement Conference, 18-20 August 2014, Chicago, U.S.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{tpd_fbew(milk, start="2018-12", end="2019-08")}
#' @export

tpd_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * tpd(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral TPD price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral TPD price index (Time Product Dummy index) extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname tpd_fbmw
#' @return This function returns a value of the multilateral TPD price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {de  Haan,  J.  and  F.  Krsinich  (2014). \emph{Time  Dummy  Hedonic  and  Quality-Adjusted  Unit Value Indexes: Do They Really Differ?} Paper presented at the Society for Economic Measurement Conference, 18-20 August 2014, Chicago, U.S.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{tpd_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

tpd_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * tpd_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral unweighted TPD price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the unweighted multilateral TPD price index (Time Product Dummy index) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname utpd_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the unweighted multilateral TPD price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {de  Haan,  J.  and  F.  Krsinich  (2014). \emph{Time  Dummy  Hedonic  and  Quality-Adjusted  Unit Value Indexes: Do They Really Differ?} Paper presented at the Society for Economic Measurement Conference, 18-20 August 2014, Chicago, U.S.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{utpd_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

utpd_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(utpd(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (utpd(data, t0, end., wstart = t0, window)*
              utpd(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, utpd(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * utpd(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * utpd(data, tT, t, wstart = tT, window) / utpd(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * utpd(data, th, t, wstart = tT, window) / utpd(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * utpd(data, tm, t, wstart = tT, window) / utpd(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * utpd(data, tT, t, wstart = tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * utpd(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * utpd(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the unweighted multilateral TPD price index by using the FBEW method.
#'
#' @description This function returns a value of the unweighted multilateral TPD price index (Time Product Dummy index) extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname utpd_fbew
#' @return This function returns a value of the unweighted multilateral TPD price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).  
#' @references
#' {de  Haan,  J.  and  F.  Krsinich  (2014). \emph{Time  Dummy  Hedonic  and  Quality-Adjusted  Unit Value Indexes: Do They Really Differ?} Paper presented at the Society for Economic Measurement Conference, 18-20 August 2014, Chicago, U.S.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{utpd_fbew(milk, start="2018-12", end="2019-08")}
#' @export

utpd_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * utpd(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the unweighted multilateral TPD price index by using the FBMW method.
#'
#' @description This function returns a value of the unweighted multilateral TPD price index (Time Product Dummy index) extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname utpd_fbmw
#' @return This function returns a value of the unweighted multilateral TPD price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {de  Haan,  J.  and  F.  Krsinich  (2014). \emph{Time  Dummy  Hedonic  and  Quality-Adjusted  Unit Value Indexes: Do They Really Differ?} Paper presented at the Society for Economic Measurement Conference, 18-20 August 2014, Chicago, U.S.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{utpd_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

utpd_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <- min(end, last)
  ind <-
  ind * utpd_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral weighted GEKS price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral weighted GEKS price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname wgeks_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral weighted GEKS price index (the weighted GEKS index based on the Fisher formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' @examples 
#' \donttest{wgeks_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

wgeks_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(wgeks(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (wgeks(data, t0, end., wstart = t0, window)*
              wgeks(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, wgeks(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * wgeks(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * wgeks(data, tT, t, wstart = tT, window) / wgeks(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * wgeks(data, th, t, wstart = tT, window) / wgeks(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * wgeks(data, tm, t, wstart = tT, window) / wgeks(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * wgeks(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * wgeks(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * wgeks(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral weighted GEKS price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeks_fbew
#' @return This function returns a value of the multilateral weighted GEKS price index (the weighted GEKS index based on the Fisher formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' @examples 
#' \donttest{wgeks_fbew(milk, start="2018-12", end="2019-08")}
#' @export

wgeks_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeks(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral weighted GEKS price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeks_fbmw
#' @return This function returns a value of the multilateral weighted GEKS price index (the weighted GEKS index based on the Fisher formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' @examples 
#' \donttest{wgeks_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

wgeks_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeks_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-L price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-L price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksl_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-L price index (the GEKS index based on the Laspeyres formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksl_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geksl_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksl(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksl(data, t0, end., wstart = t0, window)*
              geksl(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksl(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksl(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksl(data, tT, t, wstart = tT, window) / geksl(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksl(data, th, t, wstart = tT, window) / geksl(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksl(data, tm, t, wstart = tT, window) / geksl(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksl(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksl(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksl(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }
  

#' @title  Extending the multilateral GEKS-L price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-L price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksl_fbew
#' @return This function returns a value of the multilateral GEKS-L price index (the GEKS index based on the Laspeyres formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksl_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksl_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksl(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-L price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-L price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksl_fbmw
#' @return This function returns a value of the multilateral GEKS-L price index (the GEKS index based on the Laspeyres formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksl_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksl_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksl_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-L price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral weighted GEKS-L price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname wgeksl_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral weighted GEKS-L price index (the weighted GEKS index based on the Laspeyres formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksl_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

wgeksl_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(wgeksl(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (wgeksl(data, t0, end., wstart = t0, window)*
              wgeksl(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, wgeksl(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * wgeksl(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * wgeksl(data, tT, t, wstart = tT, window) / wgeksl(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * wgeksl(data, th, t, wstart = tT, window) / wgeksl(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * wgeksl(data, tm, t, wstart = tT, window) / wgeksl(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * wgeksl(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * wgeksl(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * wgeksl(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }

#' @title  Extending the multilateral weighted GEKS-L price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-L price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksl_fbew
#' @return This function returns a value of the multilateral weighted GEKS-L price index (the weighted GEKS index based on the Laspeyres formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksl_fbew(milk, start="2018-12", end="2019-08")}
#' @export

wgeksl_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksl(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-L price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-L price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksl_fbmw
#' @return This function returns a value of the multilateral weighted GEKS-L price index (the GEKS index based on the Laspeyres formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksl_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

wgeksl_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksl_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-GL price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-GL price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksgl_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-GL price index (the GEKS index based on the geometric Laspeyres formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksgl_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geksgl_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksgl(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksgl(data, t0, end., wstart = t0, window)*
              geksgl(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksgl(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksgl(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksgl(data, tT, t, wstart = tT, window) / geksgl(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksgl(data, th, t, wstart = tT, window) / geksgl(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksgl(data, tm, t, wstart = tT, window) / geksgl(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksgl(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksgl(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksgl(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }
  

#' @title  Extending the multilateral GEKS-GL price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-GL price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksgl_fbew
#' @return This function returns a value of the multilateral GEKS-GL price index (the GEKS index based on the geometric Laspeyres formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksgl_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksgl_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksgl(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-GL price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-GL price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksgl_fbmw
#' @return This function returns a value of the multilateral GEKS-GL price index (the GEKS index based on the geometric Laspeyres formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksgl_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksgl_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksgl_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-GL price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral weighted GEKS-GL price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname wgeksgl_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral weighted GEKS-GL price index (the weighted GEKS index based on the geometric Laspeyres formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksgl_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

wgeksgl_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(wgeksgl(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (wgeksgl(data, t0, end., wstart = t0, window)*
              wgeksgl(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, wgeksgl(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * wgeksgl(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * wgeksgl(data, tT, t, wstart = tT, window) / wgeksgl(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * wgeksgl(data, th, t, wstart = tT, window) / wgeksgl(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * wgeksgl(data, tm, t, wstart = tT, window) / wgeksgl(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * wgeksgl(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * wgeksgl(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * wgeksgl(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral weighted GEKS-GL price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-GL price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksgl_fbew
#' @return This function returns a value of the multilateral weighted GEKS-GL price index (the weighted GEKS index based on the geometric Laspeyres formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksgl_fbew(milk, start="2018-12", end="2019-08")}
#' @export

wgeksgl_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksgl(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-GL price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-GL price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksgl_fbmw
#' @return This function returns a value of the multilateral weighted GEKS-GL price index (the GEKS index based on the geometric Laspeyres formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksgl_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

wgeksgl_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksgl_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-AQU price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-AQU price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean","window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksaqu_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-AQU price index (the GEKS index based on the asynchronous quality adjusted unit value formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' @examples 
#' \donttest{geksaqu_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geksaqu_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksaqu(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksaqu(data, t0, end., wstart = t0, window)*
              geksaqu(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksaqu(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksaqu(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksaqu(data, tT, t, wstart = tT, window) / geksaqu(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksaqu(data, th, t, wstart = tT, window) / geksaqu(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksaqu(data, tm, t, wstart = tT, window) / geksaqu(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksaqu(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksaqu(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksaqu(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }
  

#' @title  Extending the multilateral GEKS-AQU price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-AQU price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksaqu_fbew
#' @return This function returns a value of the multilateral GEKS-AQU price index (the GEKS index based on the asynchronous quality adjusted unit value formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating,please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' @examples 
#' \donttest{geksaqu_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksaqu_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksaqu(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-AQU price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-AQU price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksaqu_fbmw
#' @return This function returns a value of the multilateral GEKS-AQU price index (the GEKS index based on the asynchronous quality adjusted unit value formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' @examples 
#' \donttest{geksaqu_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksaqu_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksaqu_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-AQU price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral weighted GEKS-AQU price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname wgeksaqu_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral weighted GEKS-AQU price index (the weighted GEKS index based on the asynchronous quality adjusted unit value formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' @examples 
#' \donttest{wgeksaqu_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

wgeksaqu_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(wgeksaqu(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (wgeksaqu(data, t0, end., wstart = t0, window)*
              wgeksaqu(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, wgeksaqu(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * wgeksaqu(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * wgeksaqu(data, tT, t, wstart = tT, window) / wgeksaqu(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * wgeksaqu(data, th, t, wstart = tT, window) / wgeksaqu(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * wgeksaqu(data, tm, t, wstart = tT, window) / wgeksaqu(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * wgeksaqu(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * wgeksaqu(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * wgeksaqu(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral weighted GEKS-AQU price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-AQU price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksaqu_fbew
#' @return This function returns a value of the multilateral weighted GEKS-AQU price index (the weighted GEKS index based on the asynchronous quality adjusted unit value formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' @examples 
#' \donttest{wgeksaqu_fbew(milk, start="2018-12", end="2019-08")}
#' @export

wgeksaqu_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksaqu(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-AQU price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-AQU price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksaqu_fbmw
#' @return This function returns a value of the multilateral weighted GEKS-AQU price index (the GEKS index based on the asynchronous quality adjusted unit value formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' @examples 
#' \donttest{wgeksaqu_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

wgeksaqu_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksaqu_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-AQI price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-AQI price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean","window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksaqi_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-AQI price index (the GEKS index based on the asynchronous quality adjusted price index formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksaqi_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

geksaqi_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksaqi(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksaqi(data, t0, end., wstart = t0, window)*
              geksaqi(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksaqi(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksaqi(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksaqi(data, tT, t, wstart = tT, window) / geksaqi(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksaqi(data, th, t, wstart = tT, window) / geksaqi(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksaqi(data, tm, t, wstart = tT, window) / geksaqi(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksaqi(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksaqi(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksaqi(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }
  

#' @title  Extending the multilateral GEKS-AQI price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-AQI price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksaqi_fbew
#' @return This function returns a value of the multilateral GEKS-AQI price index (the GEKS index based on the asynchronous quality adjusted price index formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksaqi_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksaqi_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksaqi(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-AQI price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-AQI price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksaqi_fbmw
#' @return This function returns a value of the multilateral GEKS-AQI price index (the GEKS index based on the asynchronous quality adjusted price index formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksaqi_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksaqi_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksaqi_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral weighted GEKS-AQI price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral weighted GEKS-AQI price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname wgeksaqi_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral weighted GEKS-AQI price index (the weighted GEKS index based on the asynchronous quality adjusted price index formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksaqi_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

wgeksaqi_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(wgeksaqi(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (wgeksaqi(data, t0, end., wstart = t0, window)*
              wgeksaqi(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, wgeksaqi(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * wgeksaqi(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * wgeksaqi(data, tT, t, wstart = tT, window) / wgeksaqi(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * wgeksaqi(data, th, t, wstart = tT, window) / wgeksaqi(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * wgeksaqi(data, tm, t, wstart = tT, window) / wgeksaqi(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * wgeksaqi(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * wgeksaqi(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * wgeksaqi(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral weighted GEKS-AQI price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-AQI price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksaqi_fbew
#' @return This function returns a value of the multilateral weighted GEKS-AQI price index (the weighted GEKS index based on the asynchronous quality adjusted price index formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksaqi_fbew(milk, start="2018-12", end="2019-08")}
#' @export

wgeksaqi_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksaqi(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-AQI price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-AQI price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksaqi_fbmw
#' @return This function returns a value of the multilateral weighted GEKS-AQI price index (the GEKS index based on the asynchronous quality adjusted price index formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J. (2023). \emph{Quality adjusted GEKS-type indices for price comparisons based on scanner data.} Statistics in Transition – new series, 24(3), 151-169.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{wgeksaqi_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

wgeksaqi_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksaqi_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-GAQI price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-GAQI price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean","window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksgaqi_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-GAQI price index (the GEKS index based on the geometric asynchronous quality adjusted price index formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{The general class of multilateral indices and its two special cases.} Paper presented at the 17th Meeting of the Ottawa Group on Price Indices, Rome, Italy.}
#'
#' {Białek, J., Pawelec, N. (2025). \emph{Proposition of the Quality Adjusted Geks-Type Price Index.} Statistika – Statistics and Economy Journal, 105(3), 291-305. https://doi.org/10.54694/stat.2024.71.}
#'
#' @examples 
#' \donttest{geksgaqi_splice(milk, start="2018-12", end="2020-01",window=10)}
#' @export

geksgaqi_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksgaqi(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksgaqi(data, t0, end., wstart = t0, window)*
              geksgaqi(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksgaqi(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksgaqi(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksgaqi(data, tT, t, wstart = tT, window) / geksgaqi(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksgaqi(data, th, t, wstart = tT, window) / geksgaqi(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksgaqi(data, tm, t, wstart = tT, window) / geksgaqi(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksgaqi(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksgaqi(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksgaqi(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral GEKS-GAQI price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-GAQI price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksgaqi_fbew
#' @return This function returns a value of the multilateral GEKS-GAQI price index (the GEKS index based on the geometric asynchronous quality adjusted price index formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J., Pawelec, N. (2025). \emph{Proposition of the Quality Adjusted Geks-Type Price Index.} Statistika – Statistics and Economy Journal, 105(3), 291-305. https://doi.org/10.54694/stat.2024.71.}
#'
#' @examples 
#' \donttest{geksgaqi_fbew(milk, start="2018-12", end="2019-08")}
#' @export

geksgaqi_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksgaqi(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-GAQI price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-GAQI price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname geksgaqi_fbmw
#' @return This function returns a value of the multilateral GEKS-GAQI price index (the GEKS index based on the geometric asynchronous quality adjusted price index formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J., Pawelec, N. (2025). \emph{Proposition of the Quality Adjusted Geks-Type Price Index.} Statistika – Statistics and Economy Journal, 105(3), 291-305. https://doi.org/10.54694/stat.2024.71.}
#'
#' @examples 
#' \donttest{geksgaqi_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

geksgaqi_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksgaqi_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-GAQI price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral weighted GEKS-GAQI price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname wgeksgaqi_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral weighted GEKS-GAQI price index (the weighted GEKS index based on the geometric asynchronous quality adjusted price index formula) extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J., Pawelec, N. (2025). \emph{Proposition of the Quality Adjusted Geks-Type Price Index.} Statistika – Statistics and Economy Journal, 105(3), 291-305. https://doi.org/10.54694/stat.2024.71.}
#'
#' @examples 
#' \donttest{wgeksgaqi_splice(milk, start="2018-12", end="2020-02",splice="half")}
#' @export

wgeksgaqi_splice <-
  function (data,
  start,
  end,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(wgeksgaqi(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (wgeksgaqi(data, t0, end., wstart = t0, window)*
              wgeksgaqi(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, wgeksgaqi(data, t0, t, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * wgeksgaqi(data, t1, t, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * wgeksgaqi(data, tT, t, wstart = tT, window) / wgeksgaqi(data, tT, t1, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * wgeksgaqi(data, th, t, wstart = tT, window) / wgeksgaqi(data, th, t1, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * wgeksgaqi(data, tm, t, wstart = tT, window) / wgeksgaqi(data, tm, t1, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * wgeksgaqi(data, tT, t, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * wgeksgaqi(data, th, t, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * wgeksgaqi(data, tm, t, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }

#' @title  Extending the multilateral weighted GEKS-GAQI price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-GAQI price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksgaqi_fbew
#' @return This function returns a value of the multilateral weighted GEKS-GAQI price index (the weighted GEKS index based on the geometric asynchronous quality adjusted price index formula) extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J., Pawelec, N. (2025). \emph{Proposition of the Quality Adjusted Geks-Type Price Index.} Statistika – Statistics and Economy Journal, 105(3), 291-305. https://doi.org/10.54694/stat.2024.71.}
#'
#' @examples 
#' \donttest{wgeksgaqi_fbew(milk, start="2018-12", end="2019-08")}
#' @export

wgeksgaqi_fbew <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksgaqi(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral weighted GEKS-GAQI price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral weighted GEKS-GAQI price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @rdname wgeksgaqi_fbmw
#' @return This function returns a value of the multilateral weighted GEKS-GAQI price index (the GEKS index based on the geometric asynchronous quality adjusted price index formula) extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J., Pawelec, N. (2025). \emph{Proposition of the Quality Adjusted Geks-Type Price Index.} Statistika – Statistics and Economy Journal, 105(3), 291-305. https://doi.org/10.54694/stat.2024.71.}
#'
#' @examples 
#' \donttest{wgeksgaqi_fbmw(milk, start="2019-12", end="2020-04")}
#' @export

wgeksgaqi_fbmw <- function(data, start, end)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * wgeksgaqi_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7))
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-IQM price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-IQM price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param r The real and non-zero parameter used in the implicit quadratic mean of order r price index.
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksiqm_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-IQM price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{geksiqm_splice(milk, start="2018-12", end="2020-02", r=0.8, splice="half")}
#' @export

geksiqm_splice <-
  function (data,
  start,
  end,
  r=2,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksiqm(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksiqm(data, t0, end., wstart = t0, window)*
              geksiqm(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksiqm(data, t0, t, r, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksiqm(data, t1, t, r, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksiqm(data, tT, t, r, wstart = tT, window) / geksiqm(data, tT, t1, r, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksiqm(data, th, t, r, wstart = tT, window) / geksiqm(data, th, t1, r, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksiqm(data, tm, t, r, wstart = tT, window) / geksiqm(data, tm, t1, r, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksiqm(data, tT, t, r, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksiqm(data, th, t, r, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksiqm(data, tm, t, r, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral GEKS-IQM price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-IQM price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param r The real and non-zero parameter used in the implicit quadratic mean of order r price index.
#' @rdname geksiqm_fbew
#' @return This function returns a value of the multilateral GEKS-IQM price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{geksiqm_fbew(milk, start="2018-12", end="2019-08", r=1.2)}
#' @export

geksiqm_fbew <- function(data, start, end, r)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksiqm(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  r,
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-IQM price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-IQM price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param r The real and non-zero parameter used in the implicit quadratic mean of order r price index.
#' @rdname geksiqm_fbmw
#' @return This function returns a value of the multilateral GEKS-IQM price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{geksiqm_fbmw(milk, start="2019-12", end="2020-04", r=1.6)}
#' @export

geksiqm_fbmw <- function(data, start, end, r)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksiqm_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7), r)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-QM price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-QM price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param r The real and non-zero parameter used in the implicit quadratic mean of order r price index.
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname geksqm_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-QM price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#' @examples 
#' \donttest{geksqm_splice(milk, start="2018-12", end="2020-02", r=0.8, splice="half")}
#' @export

geksqm_splice <-
  function (data,
  start,
  end,
  r=2,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(geksqm(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (geksqm(data, t0, end., wstart = t0, window)*
              geksqm(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, geksqm(data, t0, t, r, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * geksqm(data, t1, t, r, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * geksqm(data, tT, t, r, wstart = tT, window) / geksqm(data, tT, t1, r, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * geksqm(data, th, t, r, wstart = tT, window) / geksqm(data, th, t1, r, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * geksqm(data, tm, t, r, wstart = tT, window) / geksqm(data, tm, t1, r, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * geksqm(data, tT, t, r, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * geksqm(data, th, t, r, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * geksqm(data, tm, t, r, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral GEKS-QM price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-QM price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param r The real and non-zero parameter used in the implicit quadratic mean of order r price index.
#' @rdname geksqm_fbew
#' @return This function returns a value of the multilateral GEKS-QM price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#' @examples 
#' \donttest{geksqm_fbew(milk, start="2018-12", end="2019-08", r=1.2)}
#' @export

geksqm_fbew <- function(data, start, end, r)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksqm(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  r,
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-QM price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-QM price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param r The real and non-zero parameter used in the implicit quadratic mean of order r price index.
#' @rdname geksqm_fbmw
#' @return This function returns a value of the multilateral GEKS-QM price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#' @examples 
#' \donttest{geksqm_fbmw(milk, start="2019-12", end="2020-04", r=1.6)}
#' @export

geksqm_fbmw <- function(data, start, end, r)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * geksqm_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7), r)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}


#' @title  Extending the multilateral GEKS-LM price index by using window splicing methods.
#'
#' @description This function returns a value (or values) of the multilateral GEKS-LM price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}).
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param sigma The elasticity of substitution (a parameter used in the Lloyd-Moulton index formula).
#' @param window The length of the time window (as positive integer: typically multilateral methods are based on the 13-month time window).
#' @param splice A character string indicating the splicing method. Available options are: "movement", "window","half","mean", "window_published","half_published","mean_published".
#' @param interval A logical value indicating whether the function is to provide the price index comparing the research period defined by \code{end} to the base period defined by \code{start} (then \code{interval} is set to FALSE) or all fixed base multilateral indices are to be presented (the fixed base month is defined by \code{start}).
#' @rdname gekslm_splice
#' @return This function returns a value or values (depending on \code{interval} parameter) of the multilateral GEKS-LM price index extended by using window splicing methods. Available splicing methods are: movement splice, window splice, half splice, mean splice and their additional variants: window splice on published indices (WISP), half splice on published indices (HASP) and mean splice on published indices (see \code{References}). The time window starts in \code{start} and should consist of at least two months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Chessa, A. G. (2019). \emph{A Comparison of Index Extension Methods for Multilateral Methods.} Paper presented at the 16th Meeting of the Ottawa Group on Price Indices, 8-10 May 2019, Rio de Janeiro, Brazil.}
#'
#' {de Haan, J., van der Grient, H.A. (2011). \emph{Eliminating chain drift in price indexes based on scanner data.} Journal of Econometrics, 161, 36-46.}
#'
#' {Krsinich, F. (2014). \emph{The FEWS Index: Fixed Effects with a Window Splice? Non-Revisable Quality-Adjusted Price Indices with No Characteristic Information.} Paper presented at the UNECE-ILO Meeting of the Group of Experts on Consumer Price Indices, 2-4 May 2016, Geneva, Switzerland.}
#'
#' {de Haan, J.(2015). \emph{A Framework for Large Scale Use of Scanner Data in the Dutch CPI.} Paper presented at the 14th Ottawa Group meeting, Tokyo, Japan.}
#'
#' {Diewert, W.E., and Fox, K.J. (2017). \emph{Substitution Bias in Multilateral Methods for CPI Construction using Scanner Data.} Discussion paper 17-02, Vancouver School of Economics, The University of British Columbia, Vancouver, Canada.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, 57, 2893–2921. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{gekslm_splice(milk, start="2018-12", end="2020-02", sigma=0.8, splice="half")}
#' @export

gekslm_splice <-
  function (data,
  start,
  end,
  sigma=0.7,
  window = 13,
  splice = "movement",
  interval = FALSE)
  {
  L<-end.<-NULL
  asplice <-
  c(
  "movement",
  "window",
  "half",
  "mean",
  "window_published",
  "half_published",
  "mean_published"
  ) #allowed values for 'splice' parameter
  asplice2 <-
  c(
  "movement",
  "window",
  "half",
  "mean"
  ) #allowed values for speed procedure (when interval=FALSE)
  asplice3 <-
  c(
  "window_published",
  "half_published"
  ) #allowed values for speed procedure (when interval=FALSE)
  if (!(splice %in% asplice))
  stop ("The 'splice' parameter has a wrong value")
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  t0 <- start
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  wend <- start
  lubridate::month(wend) <- lubridate::month(wend) + window - 1
  #checking conditions
  if (window < 2)
  stop("window must be at least 2 months")
  if (start > end)
  stop("parameters must satisfy: start<=end")
  set <- c(1)
  #main body
  if (interval==FALSE & end <= wend) return(gekslm(data, start, end, start, window))
  if (interval==FALSE & splice %in% asplice2) {
  start<-wend
  lubridate::month(start)<-lubridate::month(start)-1
  }
  if (interval==FALSE & splice %in% asplice3) {
  if (splice=="window_published") L <- window - 1
  if (splice=="half_published") L <- floor(window / 2)
  end.<-end
  lubridate::month(end.)<-lubridate::month(end.)-L
  if (end. < wend) {
    t0 <- paste(t0, "-01", sep = "")
    t0<-as.Date(t0)
    tT <- end
    lubridate::month(tT) <-
    lubridate::month(tT) - (window - 1)
    return (gekslm(data, t0, end., wstart = t0, window)*
              gekslm(data, end., end, wstart=tT, window))
                  }
  }
  while (start < end)
  {
  lubridate::month(start) <- lubridate::month(start) + 1
  t <- substr(start, 0, 7)
  if (start <= wend)
  set <- c(set, gekslm(data, t0, t, sigma, wstart = t0, window))
  else {
  t1 <- start
  lubridate::month(t1) <-
  lubridate::month(t1) - 1
  tT <- start
  lubridate::month(tT) <-
  lubridate::month(tT) - (window - 1)
  tT1 <- start
  lubridate::month(tT1) <-
  lubridate::month(tT1) - (window - 1) - 1
  th <- start
  lubridate::month(th) <-
  lubridate::month(th) - floor(window / 2)
  t1 <- substr(t1, 0, 7)
  tT <- substr(tT, 0, 7)
  tT1 <- substr(tT1, 0, 7)
  th <- substr(th, 0, 7)
  if (splice == "movement")
  set <- c(set, set[length(set)] * gekslm(data, t1, t, sigma, wstart = tT, window))
  if (splice == "window")
  set <-
  c(
  set,
  set[length(set)] * gekslm(data, tT, t, sigma, wstart = tT, window) / gekslm(data, tT, t1, sigma, wstart =
  tT1, window)
  )
  if (splice == "half")
  set <-
  c(
  set,
  set[length(set)] * gekslm(data, th, t, sigma, wstart = tT, window) / gekslm(data, th, t1, sigma, wstart =
  tT1, window)
  )
  if (splice == "mean") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <-
  var * gekslm(data, tm, t, sigma, wstart = tT, window) / gekslm(data, tm, t1, sigma, wstart =
  tT1, window)
  }
  var <- var ^ (1 / (window - 1))
  set <-
  c(set, set[length(set)] * var)
  }
  if (splice == "window_published")
  set <-
  c(set, set[length(set) + 1 - (window - 1)] * gekslm(data, tT, t, sigma, wstart =
  tT, window))
  if (splice == "half_published")
  set <-
  c(set, set[length(set) + 1 - floor(window / 2)] * gekslm(data, th, t, sigma, wstart =
  tT, window))
  if (splice == "mean_published") {
  var <- 1
  for (m in 1:(window - 1)) {
  tm <- start
  lubridate::month(tm) <-
  lubridate::month(tm) - m
  tm <- substr(tm, 0, 7)
  var <- var * set[length(set) + 1 - m] * gekslm(data, tm, t, sigma, wstart = tT, window)
  }
  var <- var ^ (1 / (window - 1))
  set <- c(set, var)
  }
  }
  }
  if (interval == FALSE)
  return (set[length(set)])
  else
  return(set)
  }


#' @title  Extending the multilateral GEKS-LM price index by using the FBEW method.
#'
#' @description This function returns a value of the multilateral GEKS-LM price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param sigma The elasticity of substitution (a parameter used in the Lloyd-Moulton index formula)..
#' @rdname gekslm_fbew
#' @return This function returns a value of the multilateral GEKS-LM price index extended by using the FBEW (Fixed Base Monthly Expanding Window) method. The FBEW method uses a time window with a fixed base month every year (December). The  window  is  enlarged  every month  with  one  month in order to include information from a new month. The full window length (13 months) is reached in December of each year. The function measures the price dynamics between periods \code{end} and \code{start}. The month of the \code{start} parameter must be December. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Chessa, A.G. (2016). \emph{A New Methodology for Processing Scanner Data in the Dutch CPI.} Eurona 1/2016, 49-69.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, 57, 2893–2921. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{gekslm_fbew(milk, start="2018-12", end="2019-08", sigma=1.2)}
#' @export

gekslm_fbew <- function(data, start, end, sigma)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * gekslm(data,
  substr(start, 0, 7),
  substr(new, 0, 7),
  sigma,
  window = dist(start, new) + 1)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}

#' @title  Extending the multilateral GEKS-LM price index by using the FBMW method.
#'
#' @description This function returns a value of the multilateral GEKS-LM price index extended by using the FBMW (Fixed Base Moving Window) method.
#' @param data The user's data frame with information about sold products. It must contain columns: \code{time} (as Date in format: year-month-day,e.g. '2020-12-01'), \code{prices} (as positive numeric), \code{quantities}  (as positive numeric) and \code{prodID} (as numeric, factor or character).
#' @param start The base period (as character) limited to the year and month, e.g. "2019-12".
#' @param end The research period (as character) limited to the year and month, e.g. "2020-04".
#' @param sigma The elasticity of substitution (a parameter used in the Lloyd-Moulton index formula).
#' @rdname gekslm_fbmw
#' @return This function returns a value of the multilateral GEKS-LM price index extended by using the FBMW (Fixed Base Moving Window) method. It measures the price dynamics between periods \code{end} and \code{start} and it uses a 13-month time window with a fixed base month taken as \code{year(end)-1}. If the distance between \code{end} and \code{start} exceeds 13 months, then internal Decembers play a role of chain-linking months. The month of the \code{start} parameter must be December. To get information about both price index values and corresponding dates, please see functions: \code{\link{price_indices}} or \code{\link{final_index}}. The function does not take into account aggregating over outlets or product subgroups (to consider these types of aggregating, please use the \code{\link{final_index}} function).   
#' @references
#' {Gini, C. (1931). \emph{On the Circular Test of Index Numbers.} Metron 9:9, 3-24.}
#'
#' {Elteto, O., and Koves, P. (1964). \emph{On a Problem of Index Number Computation Relating to International Comparisons.} Statisztikai Szemle 42, 507-518.}
#'
#' {Szulc, B. (1983). \emph{Linking Price Index Numbers.} In: Price Level Measurement, W. E. Diewert and C. Montmarquette (eds.), 537-566.}
#'
#' {Lamboray, C.(2017). \emph{The Geary Khamis index and the Lehr index: how much do they differ?} Paper presented at the 15th Ottawa Group meeting, 10-12 May 2017, Elville am Rhein, Germany.}
#'
#' {Białek, J. (2022). \emph{Improving quality of the scanner CPI: proposition of new multilateral methods}, Quality & Quantity, 57, 2893–2921. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' {Białek, J. (2025). \emph{General Classes of GEKS-Type Price Indices With Application to Scanner  Data}, . Review of Income and Wealth, 71(1): e12726, 1-21. https://doi.org/10.1007/s11135-022-01506-6.}
#'
#' @examples 
#' \donttest{geksqm_fbmw(milk, start="2019-12", end="2020-04", r=1.6)}
#' @export

gekslm_fbmw <- function(data, start, end, sigma)  {
  if (start == end)
  return (1)
  if (nrow(data) == 0)
  stop("A data frame is empty")
  start <- paste(start, "-01", sep = "")
  end <- paste(end, "-01", sep = "")
  start <- as.Date(start)
  end <- as.Date(end)
  #checking conditions
  if (start > end)
  stop("parameters must satisfy: start<=end")
  if (lubridate::month(start) < 12)
  stop("a month of the 'start' parameter must be December")
  if (start == end)
  return (1)
  ind <- 1
  last <- as.Date(start)
  years <-
  lubridate::year(end) - lubridate::year(start)
  #main body
  for (i in 1:years) {
  lubridate::year(last) <- lubridate::year(last) + 1
  new <-
  min(end, last)
  ind <-
  ind * gekslm_fbmw2(data, substr(start, 0, 7), substr(new, 0, 7), sigma)
  lubridate::year(start) <-
  lubridate::year(start) + 1
  }
  return (ind)
}
