-----Urspr?ngliche Nachricht-----
Von: r-sig-finance-bounces at r-project.org
[mailto:r-sig-finance-bounces at r-project.org] Im Auftrag von
John P. Burkett
Gesendet: Mittwoch, 3. August 2011 18:36
An: R-SIG-Finance at r-project.org
Betreff: Re: [R-SIG-Finance] Sharpe's algorithm for portfolio
improvement
Enrico Schumann wrote:
But you can also directly use the constraint in the creation of the
new solutions, which is what Sharpe suggested (and what works quite
well, and not just for smooth functions/constraints): if
you only add
zero-sum changes to a feasible portfolio, it will remain
feasible with
respect to the budget constraint. If you want
min/max-holding sizes,
choose asset weights such that the min/max-constraints remain
unviolated. This is straightforward in methods like Simulated
Annealing/Threshold Accepting, but somewhat more difficult in 'DE'.
(Which does not mean that 'DE' is not as good as the other methods,
just that the efficient approaches possibly differ,
depending on the
method.)
Thanks, Enrico. I'm interested in using the adding-up
constraint in the creation of new solutions, via methods such
as simulated annealing or threshold accepting. I imagine
that the DMOF package is useful for implementing that
approach. Are there also other packages that I should consider?
There are many packages in R that handle optimisation, but I am not really
familiar with most if them. The task view for optimisation was already
suggested to you; you may also want to browse R-Forge/RForge.
I cannot comment on the model that you gave your other e-mail -- even
though, this objective function will essentially pick portfolios of just
very few assets with very high returns; I hope you have faith that your
return scenarios are representative of what will happen in the future.
Here is a complete example with TAopt from the NMOF package; it is mostly
copy--pasted from a package vignette. Since I don't have your data, I create
random data and put all data into one list which I later pass to the
function TAopt.
# --- #
require("NMOF")
# the neighbourhood: see the package vignette on portfolio optimisation
resample <- function(x, ...) x[sample.int(length(x), ...)] # see ?sample
neighbourU <- function(sol, data){
wn <- sol$w
toSell <- wn > data$winf
toBuy <- wn < data$wsup
i <- resample(which(toSell), size = 1L)
j <- resample(which(toBuy), size = 1L)
eps <- runif(1) * data$eps
eps <- min(wn[i] - data$winf, data$wsup - wn[j], eps)
wn[i] <- wn[i] - eps
wn[j] <- wn[j] + eps
Rw <- sol$Rw + data$R[,c(i,j)] %*% c(-eps,eps)
list(w = wn, Rw = Rw)
}
# random data
na <- 31L # number of assets
nr <- 20L # number of return obs
randomData <- rnorm(nr*na)*0.01 # random data: a plain matrix ;)
dim(randomData) <- c(nr, na)
# collect all in 'data': eps is stepsize for TA, winf/wsup are min/max
holding sizes
data <- list(R = randomData, na = na, nr = nr, eps = 0.5/100, winf = 0,
wsup = 1)
# --- #
The neighbourhood may look a bit complicated, but it uses the following
fact: in a given iteration, your objective function can be split into two
pieces: first, you compute portfolio returns Rw <- Data %*% w; then you
compute your actual objective for these returns, say, fun(Rw). The
multiplication will typically take much of the computing time (in particular
if the actual objective is quite cheap); see the following test. But the
neighbourhood function changes only two weights: increase one, decrease one.
So you can update the multiplication. In your case, this may not make much
difference >> but try with 100 or more return observations
Thus, the representation of a solution is a list with two components: the
weight vector w, and the return associated with this portfolio Rw (ie, Rw <-
Data %*% w). In the objective function, you can compute anything from sol$w
and sol$Rw.
# ---
# create a feasible random solution
w0 <- runif(data$na); w0 <- w0/sum(w0)
x0 <- list(w = w0, Rw = randomData %*% w0)
system.time(for (i in 1:100000) Rw <- randomData %*% w0)
system.time(for (i in 1:100000) ignore <- sum(Rw/(0.5 + Rw)))
# test the neighbourhood
x1 <- neighbourU(x0, data)
all.equal(data$R %*% x1$w, x1$Rw)
barplot(x0$w - x1$w) # difference between x0 and x1
# the objective function
Neu31 <- function(sol, data){
u <- sol$Rw/(0.5 + sol$Rw)
objfun <- -sum(u)/data$nr
objfun
}
# ---
Your objective: I have droppped the x1, x2, ... since they do not appear to
be needed. Also, you use an object 'nr', but never pass it. R will find it
if it is in the global environment, but I like it better to pass all objects
directly or make the dependence explicit by using environments. It remains
to run the algorithm.
# ---
# settings: see ?TAopt
algo <- list(x0 = x0, neighbour = neighbourU, nS = 2000L, nT = 10L,
nD = 1000L, q = 0.20, printBar = FALSE, printDetail = FALSE)
system.time(res <- TAopt(Neu31, algo = algo,data = data))
res$OFvalue # the obj fun value of the solution
res$xbest$w # the best weights
sum(res$xbest$w) # is budget satisfied?
# TA is a stochastic method: run restarts
allRes <- restartOpt(fun=TAopt, OF = Neu31, n = 20L, algo = algo, data =
data)
allF <- sapply(allRes, `[[`, "OFvalue") # realised objective functions
allw <- sapply(allRes,`[[`, c("xbest","w")) # weights
hope that helps,
Enrico
Best regards,
John
--
John P. Burkett
Department of Economics
University of Rhode Island
Kingston, RI 02881-0808
USA
phone (401) 874-9195
_______________________________________________
R-SIG-Finance at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance
-- Subscriber-posting only. If you want to post, subscribe first.
-- Also note that this is not the r-help list where general R
questions should go.