

This post was updated on .
I am using the PortfolioAnalytics package to run a multiperiod optimization on a quite large stock universe (14 European indicies ~ 800 stocks) but I’ve run into a problem. All examples and vignettes using the package has a fixed stock universe over the backtest period (like EDHEC) while I’ve a dynamic universe. For example, stock XYZ might have been in an index from may, 2002 to October 2007 and after that excluded from the index. However, the optimizer is only allowed to include stock XYZ in the optimization if it was part of an index at the rebalance date.
From my understanding, it is not possible to set up a custom constraint (like it is with objectives) to say that, stock XYZ should only be included in the optimization rebalancing if the rebalancing date is between may, 2002 to October 2007. Does anybody have an idea how to solve this?
DataI’ve a dataset (daily data) with a 1 if the stocks were in their respective index at the date and a 0 if they were not (see last sentence). Alternatively, I also have a list like the below with the precise dates:
Name Entry Exit
SBMONL 20030303 20150320
SMBONL 20160321 20180316
TANL 20080326 20080627
TLNLNL 20001229 20020301
TLNLNL 20040302 20051010
My returns series have the returns for the stocks for the complete listing period (not dependent on the stock being in an index or not). My current (very very ugly) workaround was to multiply the 1/0 matrix and the return matrix, so I only had returns for the periods when the stocks where in an index, and then replace all 0/NAs with 100. This 100 would penalize stocks outside of an index to such a degree, that it would not be included in the index. However, this is ugly and incorrect plus it does not work.
CodeThis is not my exact code but see this as an example of a simple optimization:
returns < read_excel("R", sheet = 1, col_names = TRUE)
returns < xts(returns[,1], order.by = as.Date(paste(returns$Dato, format = "%Y.%m.%d")))
returns < Return.calculate(returns, method = "log")
returns < returns[1,]
fund.names < colnames(returns)
tranch1 < portfolio.spec(assets = fund.names)
# Constraints
tranch1 < add.constraint(portfolio = tranch1, type = "leverage")
tranch1 < add.constraint(portfolio = tranch1, type = "long_only")
# Objective
tranch1 < add.objective(portfolio=tranch1, type="return", name="mean")
tranch1 < add.objective(portfolio=tranch1, type="risk", name="StdDev")
tranch1_opt < optimize.portfolio.rebalancing(R=returns, portfolio=tranch1,
optimize_method="DEoptim",
#momentFUN = tranch1_boudt,
#momentargs=ac.moments,
rebalance_on = “year”,
training_period = 26,
rolling_window = 26,
trace=TRUE, traceDE=5, search_size=2000)
Here is some data from my sample (dput):
structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46.276, 46.327, 46.122, 46.924,
46.071, 46.856, 47.351, 45.645, 46.003, 47.436, 48.358, 49.501,
49.364, 49.433, 48.597, 48.204, 47.061, 47.266, 47.436, 49.211,
50.729, 51.514, 51.19, 49.996, 51.156, 51.856, 51.412, 52.385,
55.797, 55.371, 54.176, 53.784, 52.896, 53.511, 54.603, 55.115,
54.654, 52.658, 52.692, 54.603, 54.569, 56.258, 54.944, 54.654,
54.552, 54.603, 53.954, 53.852, 54.262, 54.262, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 123.067, 122.712, 123.422, 127.323, 127.855, 128.032,
124.84, 117.215, 121.826, 120.939, 117.747, 122.358, 119.875,
114.91, 115.619, 113.846, 116.328, 118.634, 119.698, 120.407,
119.166, 118.811, 120.584, 120.584, 120.584, 119.875, 119.166,
120.584, 123.422, 121.294, 119.52, 123.244, 122.89, 125.018,
126.082, 125.55, 126.082, 126.259, 125.55, 126.614, 126.082,
130.692, 132.288, 132.465, 134.061, 131.047, 131.401, 133.884,
134.771, 141.155, 38.773, 39.16, 39.419, 41.067, 40.356, 41.131,
41.099, 39.548, 40.453, 40.13, 39.419, 42.327, 42.392, 43.425,
43.684, 44.976, 44.944, 44.976, 44.136, 44.362, 43.813, 43.878,
43.942, 44.298, 44.912, 45.881, 45.235, 45.558, 47.658, 47.173,
45.59, 46.786, 47.335, 47.561, 47.27, 48.337, 47.82, 46.883,
45.396, 47.432, 47.917, 48.434, 48.66, 48.983, 48.983, 48.627,
49.015, 50.728, 51.697, 51.859), .Dim = c(50L, 5L), .Dimnames = list(
NULL, c("BAERCHB4R2R5", "BALNCH7124594", "CFRCHBCRWZ1",
"CIBNCH5196744", "CLNCH7113990")), index = structure(c(883353600,
883440000, 883526400, 883699200, 883958400, 884131200, 884217600,
884304000, 884563200, 884649600, 884736000, 884822400, 884908800,
885168000, 885254400, 885340800, 885427200, 885513600, 885772800,
885859200, 885945600, 886032000, 886118400, 886377600, 886464000,
886550400, 886636800, 886723200, 886982400, 887068800, 887155200,
887241600, 887328000, 887587200, 887673600, 887760000, 887846400,
887932800, 888192000, 888278400, 888364800, 888451200, 888537600,
888796800, 888883200, 888969600, 889056000, 889142400, 889401600,
889488000), tzone = "UTC", tclass = c("POSIXct", "POSIXt")), class = c("xts",
"zoo"), .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct",
"POSIXt"), .indexTZ = "UTC", tzone = "UTC”)
As an alternative, I have also uploaded a full index here ( https://ufile.io/0cxn6 < https://ufile.io/0cxn6>) where the first sheet is the 1/0 matrix, the second the full return matrix and the third is the 1/0 matrix times the full return matrix.
[[alternative HTML version deleted]]
_______________________________________________
RSIGFinance@rproject.org mailing list
https://stat.ethz.ch/mailman/listinfo/rsigfinance Subscriberposting only. If you want to post, subscribe first.
 Also note that this is not the rhelp list where general R questions should go.


I see a few problems with your approach
1. Providing incorrect returns data for stocks when they are NOT in the
index won't work because you need the historical comovements of the stock
with the rest of the investable universe. e.g. for SharpeRatio
(MeanVariance) optimization, if the stock first entered the index on July
1, you will need accurate returns data for at least the size of the window
used to compute a covariance for July 1  e.g. if a 12month window then
for the full year prior to the first entry into the index.
2. If your optimization problem allows negative weights (i.e. short
positions), then clearly using extreme negative returns for a stock will
identify it as a good candidate for inclusion on the short side.
Possible approach:
Major index membership changes relatively infrequently. e.g. the S&P500
membership is reconstituted annually.
If your 1/0 data shows that changes are infrequent you might be able to
simply perform several runs with each run having a "constant" investable
universe for the rebalancing dates for that run. Then stitch together the
results from the different runs.
Another approach:
Contact the authors of the package to see if they have suggestions. You are
raising a standard concern and they may have addressed it or have thought
about how to deal with it.
Regards,
Eric
On Fri, Oct 19, 2018 at 12:14 AM Simon Hovmark < [hidden email]>
wrote:
> I am using the PortfolioAnalytics package to run a multiperiod
> optimization on a quite large stock universe (14 European indicies ~ 800
> stocks) but I’ve run into a problem. All examples and vignettes using the
> package has a fixed stock universe over the backtest period (like EDHEC)
> while I’ve a dynamic universe. For example, stock XYZ might have been in an
> index from may, 2002 to October 2007 and after that excluded from the
> index. However, the optimizer is only allowed to include stock XYZ in the
> optimization if it was part of an index at the rebalance date.
>
> From my understanding, it is not possible to set up a custom constraint
> (like it is with objectives) to say that, stock XYZ should only be included
> in the optimization rebalancing if the rebalancing date is between may,
> 2002 to October 2007. Does anybody have an idea how to solve this?
>
> Data
> I’ve a dataset (daily data) with a 1 if the stocks were in their
> respective index at the date and a 0 if they were not (see last sentence).
> Alternatively, I also have a list like the below with the precise dates:
>
> Name Entry Exit
> SBMONL 20030303 20150320
> SMBONL 20160321 20180316
> TANL 20080326 20080627
> TLNLNL 20001229 20020301
> TLNLNL 20040302 20051010
>
> My returns series have the returns for the stocks for the complete listing
> period (not dependent on the stock being in an index or not). My current
> (very very ugly) workaround was to multiply the 1/0 matrix and the return
> matrix, so I only had returns for the periods when the stocks where in an
> index, and then replace all 0/NAs with 100. This 100 would penalize
> stocks outside of an index to such a degree, that it would not be included
> in the index. However, this is ugly and incorrect plus it does not work.
>
> Code
> This is not my exact code but see this as an example of a simple
> optimization:
>
> returns < read_excel("R", sheet = 1, col_names = TRUE)
> returns < xts(returns[,1], order.by = as.Date(paste(returns$Dato,
> format = "%Y.%m.%d")))
> returns < Return.calculate(returns, method = "log")
> returns < returns[1,]
>
> fund.names < colnames(returns)
> tranch1 < portfolio.spec(assets = fund.names)
>
> # Constraints
> tranch1 < add.constraint(portfolio = tranch1, type = "leverage")
> tranch1 < add.constraint(portfolio = tranch1, type = "long_only")
>
> # Objective
> tranch1 < add.objective(portfolio=tranch1, type="return", name="mean")
> tranch1 < add.objective(portfolio=tranch1, type="risk", name="StdDev")
>
> tranch1_opt < optimize.portfolio.rebalancing(R=returns, portfolio=tranch1,
> optimize_method="DEoptim",
> #momentFUN = tranch1_boudt,
> #momentargs=ac.moments,
> rebalance_on = “year”,
> training_period = 26,
> rolling_window = 26,
> trace=TRUE, traceDE=5,
> search_size=2000)
>
> Here is some data from my sample (dput):
> structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46.276, 46.327, 46.122, 46.924,
> 46.071, 46.856, 47.351, 45.645, 46.003, 47.436, 48.358, 49.501,
> 49.364, 49.433, 48.597, 48.204, 47.061, 47.266, 47.436, 49.211,
> 50.729, 51.514, 51.19, 49.996, 51.156, 51.856, 51.412, 52.385,
> 55.797, 55.371, 54.176, 53.784, 52.896, 53.511, 54.603, 55.115,
> 54.654, 52.658, 52.692, 54.603, 54.569, 56.258, 54.944, 54.654,
> 54.552, 54.603, 53.954, 53.852, 54.262, 54.262, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> 0, 0, 0, 123.067, 122.712, 123.422, 127.323, 127.855, 128.032,
> 124.84, 117.215, 121.826, 120.939, 117.747, 122.358, 119.875,
> 114.91, 115.619, 113.846, 116.328, 118.634, 119.698, 120.407,
> 119.166, 118.811, 120.584, 120.584, 120.584, 119.875, 119.166,
> 120.584, 123.422, 121.294, 119.52, 123.244, 122.89, 125.018,
> 126.082, 125.55, 126.082, 126.259, 125.55, 126.614, 126.082,
> 130.692, 132.288, 132.465, 134.061, 131.047, 131.401, 133.884,
> 134.771, 141.155, 38.773, 39.16, 39.419, 41.067, 40.356, 41.131,
> 41.099, 39.548, 40.453, 40.13, 39.419, 42.327, 42.392, 43.425,
> 43.684, 44.976, 44.944, 44.976, 44.136, 44.362, 43.813, 43.878,
> 43.942, 44.298, 44.912, 45.881, 45.235, 45.558, 47.658, 47.173,
> 45.59, 46.786, 47.335, 47.561, 47.27, 48.337, 47.82, 46.883,
> 45.396, 47.432, 47.917, 48.434, 48.66, 48.983, 48.983, 48.627,
> 49.015, 50.728, 51.697, 51.859), .Dim = c(50L, 5L), .Dimnames = list(
> NULL, c("BAERCHB4R2R5", "BALNCH7124594", "CFRCHBCRWZ1",
> "CIBNCH5196744", "CLNCH7113990")), index = structure(c(883353600,
> 883440000, 883526400, 883699200, 883958400, 884131200, 884217600,
> 884304000, 884563200, 884649600, 884736000, 884822400, 884908800,
> 885168000, 885254400, 885340800, 885427200, 885513600, 885772800,
> 885859200, 885945600, 886032000, 886118400, 886377600, 886464000,
> 886550400, 886636800, 886723200, 886982400, 887068800, 887155200,
> 887241600, 887328000, 887587200, 887673600, 887760000, 887846400,
> 887932800, 888192000, 888278400, 888364800, 888451200, 888537600,
> 888796800, 888883200, 888969600, 889056000, 889142400, 889401600,
> 889488000), tzone = "UTC", tclass = c("POSIXct", "POSIXt")), class =
> c("xts",
> "zoo"), .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct",
> "POSIXt"), .indexTZ = "UTC", tzone = "UTC”)
>
> As an alternative, I have also uploaded a full index here (
> https://ufile.io/0cxn6 < https://ufile.io/0cxn6>) where the first sheet is
> the 1/0 matrix, the second the full return matrix and the third is the 1/0
> matrix times the full return matrix.
>
> [[alternative HTML version deleted]]
>
> _______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/rsigfinance>  Subscriberposting only. If you want to post, subscribe first.
>  Also note that this is not the rhelp list where general R questions
> should go.
>
[[alternative HTML version deleted]]
_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rsigfinance Subscriberposting only. If you want to post, subscribe first.
 Also note that this is not the rhelp list where general R questions should go.


Hi Simon,
A changing universe is not directly supported in PortfolioAnalytics, but it
can absolutely be done. Eric Berger mentioned several of the key concerns
with return histories of different lengths and an evolving universe of
assets. The optimize.portfolio.rebalancing function is effectively a
wrapper around optimize.portfolio. A solution to your problem with a
dynamic universe is to write your own rebalancing loop. At each iteration,
you can define the assets in the portfolio specification and the returns to
use for that iteration.
This has come up before and I would like to add it to PortfolioAnalytics,
but it has not risen to the top of my priority list. Feel free to open a
feature request on https://github.com/braverock/PortfolioAnalytics. Also,
patches always welcome.
Hope that helps.
Best,
Ross
On Fri, Oct 19, 2018 at 4:48 AM Eric Berger < [hidden email]> wrote:
> I see a few problems with your approach
> 1. Providing incorrect returns data for stocks when they are NOT in the
> index won't work because you need the historical comovements of the stock
> with the rest of the investable universe. e.g. for SharpeRatio
> (MeanVariance) optimization, if the stock first entered the index on July
> 1, you will need accurate returns data for at least the size of the window
> used to compute a covariance for July 1  e.g. if a 12month window then
> for the full year prior to the first entry into the index.
> 2. If your optimization problem allows negative weights (i.e. short
> positions), then clearly using extreme negative returns for a stock will
> identify it as a good candidate for inclusion on the short side.
>
> Possible approach:
> Major index membership changes relatively infrequently. e.g. the S&P500
> membership is reconstituted annually.
> If your 1/0 data shows that changes are infrequent you might be able to
> simply perform several runs with each run having a "constant" investable
> universe for the rebalancing dates for that run. Then stitch together the
> results from the different runs.
>
> Another approach:
> Contact the authors of the package to see if they have suggestions. You are
> raising a standard concern and they may have addressed it or have thought
> about how to deal with it.
>
> Regards,
> Eric
>
>
>
>
> On Fri, Oct 19, 2018 at 12:14 AM Simon Hovmark < [hidden email]>
> wrote:
>
> > I am using the PortfolioAnalytics package to run a multiperiod
> > optimization on a quite large stock universe (14 European indicies ~ 800
> > stocks) but I’ve run into a problem. All examples and vignettes using the
> > package has a fixed stock universe over the backtest period (like EDHEC)
> > while I’ve a dynamic universe. For example, stock XYZ might have been in
> an
> > index from may, 2002 to October 2007 and after that excluded from the
> > index. However, the optimizer is only allowed to include stock XYZ in the
> > optimization if it was part of an index at the rebalance date.
> >
> > From my understanding, it is not possible to set up a custom constraint
> > (like it is with objectives) to say that, stock XYZ should only be
> included
> > in the optimization rebalancing if the rebalancing date is between may,
> > 2002 to October 2007. Does anybody have an idea how to solve this?
> >
> > Data
> > I’ve a dataset (daily data) with a 1 if the stocks were in their
> > respective index at the date and a 0 if they were not (see last
> sentence).
> > Alternatively, I also have a list like the below with the precise dates:
> >
> > Name Entry Exit
> > SBMONL 20030303 20150320
> > SMBONL 20160321 20180316
> > TANL 20080326 20080627
> > TLNLNL 20001229 20020301
> > TLNLNL 20040302 20051010
> >
> > My returns series have the returns for the stocks for the complete
> listing
> > period (not dependent on the stock being in an index or not). My current
> > (very very ugly) workaround was to multiply the 1/0 matrix and the
> return
> > matrix, so I only had returns for the periods when the stocks where in an
> > index, and then replace all 0/NAs with 100. This 100 would penalize
> > stocks outside of an index to such a degree, that it would not be
> included
> > in the index. However, this is ugly and incorrect plus it does not work.
> >
> > Code
> > This is not my exact code but see this as an example of a simple
> > optimization:
> >
> > returns < read_excel("R", sheet = 1, col_names = TRUE)
> > returns < xts(returns[,1], order.by = as.Date(paste(returns$Dato,
> > format = "%Y.%m.%d")))
> > returns < Return.calculate(returns, method = "log")
> > returns < returns[1,]
> >
> > fund.names < colnames(returns)
> > tranch1 < portfolio.spec(assets = fund.names)
> >
> > # Constraints
> > tranch1 < add.constraint(portfolio = tranch1, type = "leverage")
> > tranch1 < add.constraint(portfolio = tranch1, type = "long_only")
> >
> > # Objective
> > tranch1 < add.objective(portfolio=tranch1, type="return", name="mean")
> > tranch1 < add.objective(portfolio=tranch1, type="risk", name="StdDev")
> >
> > tranch1_opt < optimize.portfolio.rebalancing(R=returns,
> portfolio=tranch1,
> > optimize_method="DEoptim",
> > #momentFUN = tranch1_boudt,
> > #momentargs=ac.moments,
> > rebalance_on = “year”,
> > training_period = 26,
> > rolling_window = 26,
> > trace=TRUE, traceDE=5,
> > search_size=2000)
> >
> > Here is some data from my sample (dput):
> > structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> > 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> > 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46.276, 46.327, 46.122, 46.924,
> > 46.071, 46.856, 47.351, 45.645, 46.003, 47.436, 48.358, 49.501,
> > 49.364, 49.433, 48.597, 48.204, 47.061, 47.266, 47.436, 49.211,
> > 50.729, 51.514, 51.19, 49.996, 51.156, 51.856, 51.412, 52.385,
> > 55.797, 55.371, 54.176, 53.784, 52.896, 53.511, 54.603, 55.115,
> > 54.654, 52.658, 52.692, 54.603, 54.569, 56.258, 54.944, 54.654,
> > 54.552, 54.603, 53.954, 53.852, 54.262, 54.262, 0, 0, 0, 0, 0,
> > 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> > 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> > 0, 0, 0, 123.067, 122.712, 123.422, 127.323, 127.855, 128.032,
> > 124.84, 117.215, 121.826, 120.939, 117.747, 122.358, 119.875,
> > 114.91, 115.619, 113.846, 116.328, 118.634, 119.698, 120.407,
> > 119.166, 118.811, 120.584, 120.584, 120.584, 119.875, 119.166,
> > 120.584, 123.422, 121.294, 119.52, 123.244, 122.89, 125.018,
> > 126.082, 125.55, 126.082, 126.259, 125.55, 126.614, 126.082,
> > 130.692, 132.288, 132.465, 134.061, 131.047, 131.401, 133.884,
> > 134.771, 141.155, 38.773, 39.16, 39.419, 41.067, 40.356, 41.131,
> > 41.099, 39.548, 40.453, 40.13, 39.419, 42.327, 42.392, 43.425,
> > 43.684, 44.976, 44.944, 44.976, 44.136, 44.362, 43.813, 43.878,
> > 43.942, 44.298, 44.912, 45.881, 45.235, 45.558, 47.658, 47.173,
> > 45.59, 46.786, 47.335, 47.561, 47.27, 48.337, 47.82, 46.883,
> > 45.396, 47.432, 47.917, 48.434, 48.66, 48.983, 48.983, 48.627,
> > 49.015, 50.728, 51.697, 51.859), .Dim = c(50L, 5L), .Dimnames = list(
> > NULL, c("BAERCHB4R2R5", "BALNCH7124594", "CFRCHBCRWZ1",
> > "CIBNCH5196744", "CLNCH7113990")), index = structure(c(883353600,
> > 883440000, 883526400, 883699200, 883958400, 884131200, 884217600,
> > 884304000, 884563200, 884649600, 884736000, 884822400, 884908800,
> > 885168000, 885254400, 885340800, 885427200, 885513600, 885772800,
> > 885859200, 885945600, 886032000, 886118400, 886377600, 886464000,
> > 886550400, 886636800, 886723200, 886982400, 887068800, 887155200,
> > 887241600, 887328000, 887587200, 887673600, 887760000, 887846400,
> > 887932800, 888192000, 888278400, 888364800, 888451200, 888537600,
> > 888796800, 888883200, 888969600, 889056000, 889142400, 889401600,
> > 889488000), tzone = "UTC", tclass = c("POSIXct", "POSIXt")), class =
> > c("xts",
> > "zoo"), .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct",
> > "POSIXt"), .indexTZ = "UTC", tzone = "UTC”)
> >
> > As an alternative, I have also uploaded a full index here (
> > https://ufile.io/0cxn6 < https://ufile.io/0cxn6>) where the first sheet
> is
> > the 1/0 matrix, the second the full return matrix and the third is the
> 1/0
> > matrix times the full return matrix.
> >
> > [[alternative HTML version deleted]]
> >
> > _______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/rsigfinance> >  Subscriberposting only. If you want to post, subscribe first.
> >  Also note that this is not the rhelp list where general R questions
> > should go.
> >
>
> [[alternative HTML version deleted]]
>
> _______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/rsigfinance>  Subscriberposting only. If you want to post, subscribe first.
>  Also note that this is not the rhelp list where general R questions
> should go.
>
[[alternative HTML version deleted]]
_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rsigfinance Subscriberposting only. If you want to post, subscribe first.
 Also note that this is not the rhelp list where general R questions should go.


Thanks for your answers! I agree that my current solution was.. nonoptimal.
The rebalancing loop around optimize.portfolio seems as the way to go. I’m
not that skilled in R yet and this is for a school project (hard deadline),
so I will probably go with Eric’s solution for now about dividing the data
into pieces determined by the rebalancing dates (yearly) and then sort away
does stocks not in an index at that given date.
But the rebalancing loop could be a nice project for learning and if I get
to a decent result, I’ll post it here.
Simon
> Den 19. okt. 2018 kl. 09.45 skrev Ross Bennett < [hidden email]>:
>
> Hi Simon,
>
> A changing universe is not directly supported in PortfolioAnalytics, but it
> can absolutely be done. Eric Berger mentioned several of the key concerns
> with return histories of different lengths and an evolving universe of
> assets. The optimize.portfolio.rebalancing function is effectively a
> wrapper around optimize.portfolio. A solution to your problem with a
> dynamic universe is to write your own rebalancing loop. At each iteration,
> you can define the assets in the portfolio specification and the returns to
> use for that iteration.
>
> This has come up before and I would like to add it to PortfolioAnalytics,
> but it has not risen to the top of my priority list. Feel free to open a
> feature request on https://github.com/braverock/PortfolioAnalytics < https://github.com/braverock/PortfolioAnalytics>. Also,
> patches always welcome.
>
> Hope that helps.
>
> Best,
> Ross
>
> On Fri, Oct 19, 2018 at 4:48 AM Eric Berger < [hidden email] <mailto: [hidden email]>> wrote:
>
>> I see a few problems with your approach
>> 1. Providing incorrect returns data for stocks when they are NOT in the
>> index won't work because you need the historical comovements of the stock
>> with the rest of the investable universe. e.g. for SharpeRatio
>> (MeanVariance) optimization, if the stock first entered the index on July
>> 1, you will need accurate returns data for at least the size of the window
>> used to compute a covariance for July 1  e.g. if a 12month window then
>> for the full year prior to the first entry into the index.
>> 2. If your optimization problem allows negative weights (i.e. short
>> positions), then clearly using extreme negative returns for a stock will
>> identify it as a good candidate for inclusion on the short side.
>>
>> Possible approach:
>> Major index membership changes relatively infrequently. e.g. the S&P500
>> membership is reconstituted annually.
>> If your 1/0 data shows that changes are infrequent you might be able to
>> simply perform several runs with each run having a "constant" investable
>> universe for the rebalancing dates for that run. Then stitch together the
>> results from the different runs.
>>
>> Another approach:
>> Contact the authors of the package to see if they have suggestions. You are
>> raising a standard concern and they may have addressed it or have thought
>> about how to deal with it.
>>
>> Regards,
>> Eric
>>
>>
>>
>>
>> On Fri, Oct 19, 2018 at 12:14 AM Simon Hovmark < [hidden email] <mailto: [hidden email]>>
>> wrote:
>>
>>> I am using the PortfolioAnalytics package to run a multiperiod
>>> optimization on a quite large stock universe (14 European indicies ~ 800
>>> stocks) but I’ve run into a problem. All examples and vignettes using the
>>> package has a fixed stock universe over the backtest period (like EDHEC)
>>> while I’ve a dynamic universe. For example, stock XYZ might have been in
>> an
>>> index from may, 2002 to October 2007 and after that excluded from the
>>> index. However, the optimizer is only allowed to include stock XYZ in the
>>> optimization if it was part of an index at the rebalance date.
>>>
>>> From my understanding, it is not possible to set up a custom constraint
>>> (like it is with objectives) to say that, stock XYZ should only be
>> included
>>> in the optimization rebalancing if the rebalancing date is between may,
>>> 2002 to October 2007. Does anybody have an idea how to solve this?
>>>
>>> Data
>>> I’ve a dataset (daily data) with a 1 if the stocks were in their
>>> respective index at the date and a 0 if they were not (see last
>> sentence).
>>> Alternatively, I also have a list like the below with the precise dates:
>>>
>>> Name Entry Exit
>>> SBMONL 20030303 20150320
>>> SMBONL 20160321 20180316
>>> TANL 20080326 20080627
>>> TLNLNL 20001229 20020301
>>> TLNLNL 20040302 20051010
>>>
>>> My returns series have the returns for the stocks for the complete
>> listing
>>> period (not dependent on the stock being in an index or not). My current
>>> (very very ugly) workaround was to multiply the 1/0 matrix and the
>> return
>>> matrix, so I only had returns for the periods when the stocks where in an
>>> index, and then replace all 0/NAs with 100. This 100 would penalize
>>> stocks outside of an index to such a degree, that it would not be
>> included
>>> in the index. However, this is ugly and incorrect plus it does not work.
>>>
>>> Code
>>> This is not my exact code but see this as an example of a simple
>>> optimization:
>>>
>>> returns < read_excel("R", sheet = 1, col_names = TRUE)
>>> returns < xts(returns[,1], order.by = as.Date(paste(returns$Dato,
>>> format = "%Y.%m.%d")))
>>> returns < Return.calculate(returns, method = "log")
>>> returns < returns[1,]
>>>
>>> fund.names < colnames(returns)
>>> tranch1 < portfolio.spec(assets = fund.names)
>>>
>>> # Constraints
>>> tranch1 < add.constraint(portfolio = tranch1, type = "leverage")
>>> tranch1 < add.constraint(portfolio = tranch1, type = "long_only")
>>>
>>> # Objective
>>> tranch1 < add.objective(portfolio=tranch1, type="return", name="mean")
>>> tranch1 < add.objective(portfolio=tranch1, type="risk", name="StdDev")
>>>
>>> tranch1_opt < optimize.portfolio.rebalancing(R=returns,
>> portfolio=tranch1,
>>> optimize_method="DEoptim",
>>> #momentFUN = tranch1_boudt,
>>> #momentargs=ac.moments,
>>> rebalance_on = “year”,
>>> training_period = 26,
>>> rolling_window = 26,
>>> trace=TRUE, traceDE=5,
>>> search_size=2000)
>>>
>>> Here is some data from my sample (dput):
>>> structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>>> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>>> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46.276, 46.327, 46.122, 46.924,
>>> 46.071, 46.856, 47.351, 45.645, 46.003, 47.436, 48.358, 49.501,
>>> 49.364, 49.433, 48.597, 48.204, 47.061, 47.266, 47.436, 49.211,
>>> 50.729, 51.514, 51.19, 49.996, 51.156, 51.856, 51.412, 52.385,
>>> 55.797, 55.371, 54.176, 53.784, 52.896, 53.511, 54.603, 55.115,
>>> 54.654, 52.658, 52.692, 54.603, 54.569, 56.258, 54.944, 54.654,
>>> 54.552, 54.603, 53.954, 53.852, 54.262, 54.262, 0, 0, 0, 0, 0,
>>> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>>> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
>>> 0, 0, 0, 123.067, 122.712, 123.422, 127.323, 127.855, 128.032,
>>> 124.84, 117.215, 121.826, 120.939, 117.747, 122.358, 119.875,
>>> 114.91, 115.619, 113.846, 116.328, 118.634, 119.698, 120.407,
>>> 119.166, 118.811, 120.584, 120.584, 120.584, 119.875, 119.166,
>>> 120.584, 123.422, 121.294, 119.52, 123.244, 122.89, 125.018,
>>> 126.082, 125.55, 126.082, 126.259, 125.55, 126.614, 126.082,
>>> 130.692, 132.288, 132.465, 134.061, 131.047, 131.401, 133.884,
>>> 134.771, 141.155, 38.773, 39.16, 39.419, 41.067, 40.356, 41.131,
>>> 41.099, 39.548, 40.453, 40.13, 39.419, 42.327, 42.392, 43.425,
>>> 43.684, 44.976, 44.944, 44.976, 44.136, 44.362, 43.813, 43.878,
>>> 43.942, 44.298, 44.912, 45.881, 45.235, 45.558, 47.658, 47.173,
>>> 45.59, 46.786, 47.335, 47.561, 47.27, 48.337, 47.82, 46.883,
>>> 45.396, 47.432, 47.917, 48.434, 48.66, 48.983, 48.983, 48.627,
>>> 49.015, 50.728, 51.697, 51.859), .Dim = c(50L, 5L), .Dimnames = list(
>>> NULL, c("BAERCHB4R2R5", "BALNCH7124594", "CFRCHBCRWZ1",
>>> "CIBNCH5196744", "CLNCH7113990")), index = structure(c(883353600,
>>> 883440000, 883526400, 883699200, 883958400, 884131200, 884217600,
>>> 884304000, 884563200, 884649600, 884736000, 884822400, 884908800,
>>> 885168000, 885254400, 885340800, 885427200, 885513600, 885772800,
>>> 885859200, 885945600, 886032000, 886118400, 886377600, 886464000,
>>> 886550400, 886636800, 886723200, 886982400, 887068800, 887155200,
>>> 887241600, 887328000, 887587200, 887673600, 887760000, 887846400,
>>> 887932800, 888192000, 888278400, 888364800, 888451200, 888537600,
>>> 888796800, 888883200, 888969600, 889056000, 889142400, 889401600,
>>> 889488000), tzone = "UTC", tclass = c("POSIXct", "POSIXt")), class =
>>> c("xts",
>>> "zoo"), .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct",
>>> "POSIXt"), .indexTZ = "UTC", tzone = "UTC”)
>>>
>>> As an alternative, I have also uploaded a full index here (
>>> https://ufile.io/0cxn6 < https://ufile.io/0cxn6> < https://ufile.io/0cxn6 < https://ufile.io/0cxn6>>) where the first sheet
>> is
>>> the 1/0 matrix, the second the full return matrix and the third is the
>> 1/0
>>> matrix times the full return matrix.
>>>
>>> [[alternative HTML version deleted]]
>>>
>>> _______________________________________________
>>> [hidden email] <mailto: [hidden email]> mailing list
>>> https://stat.ethz.ch/mailman/listinfo/rsigfinance < https://stat.ethz.ch/mailman/listinfo/rsigfinance>
>>>  Subscriberposting only. If you want to post, subscribe first.
>>>  Also note that this is not the rhelp list where general R questions
>>> should go.
>>>
>>
>> [[alternative HTML version deleted]]
>>
>> _______________________________________________
>> [hidden email] <mailto: [hidden email]> mailing list
>> https://stat.ethz.ch/mailman/listinfo/rsigfinance < https://stat.ethz.ch/mailman/listinfo/rsigfinance>
>>  Subscriberposting only. If you want to post, subscribe first.
>>  Also note that this is not the rhelp list where general R questions
>> should go.
>>
>
> [[alternative HTML version deleted]]
>
> _______________________________________________
> [hidden email] <mailto: [hidden email]> mailing list
> https://stat.ethz.ch/mailman/listinfo/rsigfinance < https://stat.ethz.ch/mailman/listinfo/rsigfinance>
>  Subscriberposting only. If you want to post, subscribe first.
>  Also note that this is not the rhelp list where general R questions should go.
[[alternative HTML version deleted]]
_______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/rsigfinance Subscriberposting only. If you want to post, subscribe first.
 Also note that this is not the rhelp list where general R questions should go.

