Тестване на стратегия за търговия в R с помощта на quantmod: Функция и for цикъл във функция

Използвам пакети R, quantmod и Performanceanalystics. Като част от стратегия за бектестване, аз се опитвам да създам вектор на сигнала/притежанията, който ми казва дали трябва да купя/продам/задържа акция въз основа на стойността на RSI. Ако RSI‹30, купете (така притежанията се увеличават с 1), ако RSI е между 30 и 50, не правете нищо (така притежанията остават същите като вчера). Ако RSI>=50, продайте всичко (така притежанията стават нула). След това използвайте функцията dailyReturn() от Performanceanalytics, за да изчислите и генерирате графика на възвръщаемостта.

Обърнете внимание, че RSI() е функция, която приема "цена" и "ден", а функцията dailyReturn() също приема "цена"

Успях да се справя перфектно със следния код по-долу.

library(quantmod)
library(PerformanceAnalytics)
getSymbols("IBM", src= "yahoo", from = "2000-01-01", to ="2015-09-25")

rsi<-RSI(Cl(IBM),14)
rsi<-lag(rsi,1)
rsi[is.na(rsi)] <- 0 

holdings1 <-c() #initialize the vector
holdings1[1:14+1]<-0  #Not holding any shares of IBM from 1st to the 15th day
for (i in 14+2: length(Cl(IBM))){ #assume start buying from the 16th day onwards since we are using RSI where n=14
 if (rsi[i]<30){ #if RSI<30, we buy one share of IBM
  holdings1[i]<-holdings1[i-1]+1  
  } else if (rsi[i]>50){ # if RSI>50, we sell all holdings
  holdings1[i]<-0
 } else 
   holdings1[i]<- holdings1[i-1] # remains the same: if 30<=RSI<=50 we don't do anything, so same holdings as prior
 }
size1<-reclass(holdings1,Cl(IBM))
ret1<-dailyReturn(Cl(IBM))*size1
charts.PerformanceSummary(ret1)

Но от мен се изисква да създам функция, наречена "size1()", която приема "цена" и "ден" (професорът казва, а аз не се занимавам с компютри). Когато се опитам да направя това, RStudio ми казва „Грешка в lag(rsi, 1): обектът „rsi“ не е намерен“. Защо така? Не е ли законно да се създаде функция или вектор във функция? Или трябва да структурирам кода си по начин, различен от първия по-горе? Кодът с функция (цена, ден) е по-долу:

library(quantmod)
library(PerformanceAnalytics)
getSymbols("IBM", src= "yahoo", from = "2000-01-01", to ="2015-09-25") #download IBM, from the stipulated range of dates

size1<-function(price,day){
  ris<-RSI(price,day)
  ris<-lag(rsi,1)
  rsi[is.na(rsi)] <- 0
  holdings1<-c()
  holdings1[1:day+1]<-0
 for (i in day+2: length(price)){ #assume start buying from the 15th day onwards since we are using RSI, n=14
  if (rsi[i]<30){ #if RSI<30, we buy one share of IBM
    holdings1[i]<-holdings1[i-1]+1  
  } else if (rsi[i]<50){ # if 30<RSI<50, we don't buy or sell, so that the holdings does not change
    holdings1[i]<-holdings1[i-1]
  } else 
    holdings1[i]<-0 # sell all if RSI>50
  size<-reclass(holdings1,price)
  }
}

ret1<-dailyReturn(Cl(IBM))*size1(Cl(IBM),14)
charts.PerformanceSummary(ret1) 

person Siang Ee Eo    schedule 11.10.2015    source източник
comment
Имате правописна грешка в кода си: ris не е rsi.   -  person Joshua Ulrich    schedule 11.10.2015
comment
Здравейте, току-що редактирано, все още не работи. ret1<-dailyReturn(Cl(IBM))*size1(Cl(IBM),14) (Грешка в [.xts(rsi, i) : долен индекс извън границите) charts.PerformanceSummary(ret1) (Грешка в inherits(x, xts) : обектът 'ret1' не е намерен)   -  person Siang Ee Eo    schedule 11.10.2015


Отговори (1)


day+2:length(price) не е това, което очаквате. : има предимство пред + (вижте ?Syntax). Оценява се на day + (2:length(price)). Искаш (day+2):length(price). Също така имайте предвид, че обектите xts са матрица с атрибут index, а матрицата е просто вектор с атрибут dim. Извикването на length на матрица връща общия брой наблюдения (length на вектора). Вместо това трябва да използвате nrow.

Също така е добра практика да разпределите предварително целия резултатен вектор преди цикъла for. Текущият ви код се добавя към holdings всеки път, когато извиквате holdings[i] <-, когато i е по-голям от текущата дължина на holdings.

Освен това вашата функция в момента не връща нищо. Изглежда, че възнамерявате да върнете обекта size. Имайте предвид, че не е необходимо да създавате отново този обект при всяка итерация на цикъл.

size1 <- function (price, day) {
    rsi <- RSI(price, day)
    rsi <- lag(rsi, 1)
    rsi[is.na(rsi)] <- 0
    holdings1 <- integer(nrow(price))
    # assume start buying from the 15th day onwards,
    # since we are using RSI, n=14
    for (i in (day+1):nrow(price)) {
        if (rsi[i] < 30) {
            # if RSI<30, we buy one share of IBM
            holdings1[i] <- holdings1[i - 1] + 1
        }
        else if (rsi[i] < 50) {
            # if 30<RSI<50, we don't buy or sell,
            # so that the holdings does not change
            holdings1[i] <- holdings1[i - 1]
        } else {
            # sell all if RSI>50
            holdings1[i] <- 0
        }
    }
    reclass(holdings1, price)
}
person Joshua Ulrich    schedule 11.10.2015
comment
Здравей, благодаря! :) Проработи. Не съм толкова добър в разграничаването на неща като c(), length() и nrow(), но сега виждам, че nrow() е по-добрият за използване. Мисля, че ще стана по-добър с повече практика. Благодаря отново! - person Siang Ee Eo; 12.10.2015
comment
@SiangEeEo: Също така имайте предвид, че извикването на nrow на вектор ще върне NULL, така че е по-безопасно да използвате NROWNCOL), ако не сте сигурни. - person Joshua Ulrich; 12.10.2015