Общая функция, добавляющая сегменты к графику в quantmod

Я пытаюсь написать простую функцию в формате add_TA, которая добавляет общие сегменты к графику. Функция получит матрицу N на 4. Каждая строка в матрице является сегментом.

Я пытался изменить add_SMA под свои нужды, но безуспешно.

add_Segments <- function (segs , ...) 
{
    lenv <- new.env()
    lenv$add_segments <- function(segs , ...) {
        segments(segs[,1] , segs[,2] , segs[,3] , segs[,4] , ...)
    }
    mapply(function(name, value) {
        assign(name, value, envir = lenv)
    }, names(list(segs = segs , ...)), list(segs = segs, ...))  
    plot_object <- current.chob()
    lenv$xdata <- segs
    plot_object$set_frame(2)
    exp <- parse(text = "add_segments(segs = segs , ...)")
    plot_object$add(exp, env = c(lenv, plot_object$Env), expr = TRUE)
    plot_object
}

Это терпит неудачу с

Error in plot.window(c(1, 1658), c(NaN, NaN)) : need finite 'ylim' values

Хотя я позаботился об этом, когда установил xdata в lenv, но, думаю, я этого не сделал.

Это воспроизводимый пример, иллюстрирующий результат и правильную работу segments.

require(quantmod)
s <- get(getSymbols('MSFT'))["2012"]
chart_Series(s)
segs <- matrix(c(183,31.61,213,30.20,221,26.34,233,26.26) , byrow = T , nrow = 2)
segments(segs[,1] , segs[,2] , segs[,3] , segs[,4] , col = 'red')

Причина, по которой я использую формат add_TA (а не просто рисование, как в приведенном выше примере), заключается в том, что я хочу добавить дополнительные индикаторы и хочу, чтобы сегменты оставались на графике после обновления объекта графика.


person haki    schedule 06.08.2013    source источник


Ответы (1)


Вы можете сделать это с помощью функции add_Series, но вам придется немного больше манипулировать, чтобы получить данные в правильном формате. Функция ниже делает эти манипуляции за вас.

interp <- function(Data, Points) {
  # merge points with original data to create NA
  m <- merge(Data[Points], index(Data))
  # linear approximation at equidistant spacing,
  # rather than at index values (the default)
  na.approx(m, seq(nrow(Data)))
}

chart_Series(s)
add_Series(interp(Hi(s), c(183,213)), type="line", on=1)
add_Series(interp(Lo(s), c(221,233)), type="line", on=1)
person Joshua Ulrich    schedule 06.08.2013
comment
Спасибо @Джошуа. Замечательно. Но одно но - я не мог заставить его работать ни с add_Series, ни с add_TA(.. , type= 'l'). единственный способ нарисовать линию на графике - это когда я использую add_TA(x , type = 'p'). У вас есть идеи, почему это так? - person haki; 07.08.2013
comment
Привет, @Joshua, я только что протестировал функцию с 43 строками в ежедневном временном ряду с 2007 по 2013 год. На выполнение ушло +30 секунд. Я предполагаю, что слияние и аппроксимация занимают много времени. поскольку в этом случае они не нужны, мы используем их, чтобы иметь возможность использовать существующий интерфейс. Может быть, вы придумаете способ заставить его работать с сегментами, а не с сериями? - person haki; 07.08.2013
comment
@haki: что ты имеешь в виду, ты не мог заставить это работать? Меня устраивает. Причина, по которой 43 строки занимают так много времени, вероятно, заключается в том, что вы вызываете функции, как я делаю в своем ответе, что приводит к перерисовке графика после каждого вызова функции. Поместите все вызовы add_Series в аргумент TA= функции chart_Series. Например, chart_Series(s, TA="add_Series(...);add_Series(...);..."). - person Joshua Ulrich; 07.08.2013