Restrict amounts for individual assets in various ways.
This presumes that you can do basic random portfolio generation. For example, that you have mastered “Very simple long-only”.
- Portfolio Probe
You need to have the Portfolio Probe package loaded into your R session:
If you don’t have Portfolio Probe, see “Demo or Buy”.
Doing the example
- The objects:
curPortfolthat are defined in several examples, such as in “Passive, no benchmark (minimum variance)”
xaLWvar06variance matrix from “Returns to variance matrix” example
We will generate random portfolios that:
- limit maximum weight of assets
- limit the contribution to portfolio variance of assets
- limit minimum and maximum amount in a long-only portfolio
- limit amount traded by asset
Limit maximum weight of assets
We generate portfolios that restrict the maximum weight to 10%:
rpMaxWt <- random.portfolio(100, priceVector, existing=curPortfol, gross=grossVal, long.only=TRUE, max.weight=.1)
We can get the maximum weight in each portfolio and then do a summary of those numbers:
> summary(sapply(valuation(rpMaxWt, priceVector, + weight=TRUE), max)) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.08140 0.09079 0.09527 0.09479 0.09830 0.10000
Limit the contribution to portfolio variance of assets
The constraint in the previous example — limiting maximum weight — is quite commonly done, but is not likely to be what people really want. Closer to what is wanted is to constrain the amount of risk that each asset brings to the portfolio.
Do that with:
rpRiskFrac <- random.portfolio(100, priceVector, variance=xaLWvar06, existing=curPortfol, gross=grossVal, long.only=TRUE, risk.fraction=.1)
There are two changes between this and the previous example: “
max.weight” is changed to “
risk.fraction“, and a variance matrix is given.
The summary of the maximum weights is:
> summary(sapply(valuation(rpRiskFrac, priceVector, + weight=TRUE), max)) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.04648 0.07284 0.08416 0.09031 0.09394 0.17360
Since we are restricting risk rather than weight, the maximum weight can be bigger than 10%. Interestingly there are some portfolios with quite low maximum weight as well.
Limit minimum and maximum amount in a long-only portfolio
There is no “min.weight” argument to match the
max.weight argument. One way of getting a minimum weight constraint is to use the
To get a minimum weight of 5% and maximum weight of 20% for all assets, we can set up the
positions argument as:
posArg <- cbind(rep(.05, 10), .2) * grossVal
This argument expects its inputs in terms of money. The first few rows look like:
> head(posArg, 3) [,1] [,2] [1,] 151671.5 606686 [2,] 151671.5 606686 [3,] 151671.5 606686
Now we can generate the portfolios . Note that we are restricting the universe to only the first 10 assets (the ones that are in the existing portfolio):
rpMinMaxWt <- random.portfolio(100, head(priceVector, 10), existing=curPortfol, gross=grossVal, long.only=TRUE, positions=posArg)
The summary of minimum weights is:
> summary(sapply(valuation(rpMinMaxWt, priceVector, + weight=TRUE), min)) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.05000 0.05001 0.05291 0.05391 0.05672 0.06965
Limit amount traded by asset
We can limit the number of units (that is, shares, contracts, …) that are traded by asset with the arguments
First we create a vector for the maximum number of shares we are willing to sell for each of the assets in the existing portfolio:
lowArg <- seq(-1500, by=100, length=10) names(lowArg) <- names(curPortfol)
This looks like:
XA101 XA103 XA105 XA107 XA108 XA111 XA113 XA115 -1500 -1400 -1300 -1200 -1100 -1000 -900 -800 XA120 XA126 -700 -600
In general the
upper.trade need not be related to the values in
lower.trade, but in the interests of simplicity we’ll make the trading limits symmetric:
rpLoHiTrade <- random.portfolio(100, priceVector, existing=curPortfol, gross=grossVal, long.only=TRUE, lower.trade=lowArg, upper.trade=-lowArg)
This restricts the trading of the ten assets named in
lowArg but not any of the other assets. Often all assets are restricted, but you can constrain or not constrain any assets as you please.
A blanket weight constraint as in the first example is almost surely better as a risk fraction constraint. However, there are maximum weight constraints that do make sense. For example, you may want to hold no more than x days of average volume of each asset. That can be stated as a maximum weight, but will be a different weight for each asset.
To give such a constraint, give a named vector to
max.weight. For example:
max.weight=c(XA101=.057, XA103=.015, XA120=.712)
This constrains the three assets named but does not constrain any others.
The generalization of the
max.weight argument explained just above also works for
risk.fraction. It is possible to put a lower bound on the risk fractions as well (in the same spirit as the third example).
Minimum and maximum amount
The matrix that we gave to the
positions argument had all its rows the same. In order to give different amounts for different assets, the matrix needs row names that are the identifiers of the assets.
Lower and upper trade
The values in
lower.trade need to be negative or zero, and the values in
upper.trade need to be positive or zero.
Otherwise, they would be forcing a trade. You can force trades, but you need to use either the
forced.trade argument or the
The example with minimum weights was restricted to have only 10 assets in the universe because that form of constraint says that all assets should obey it. If instead you want a minimum weight given that the asset is in the portfolio at all, then that is a threshold constraint. Threshold constraints may be imposed either with the
threshold argument or with the
positions argument (using more columns).
For long-short portfolios,
max.weight constrains the absolute value of the weight. In this case weight is defined as the position value divided by the gross value of the portfolio.
- Be mindful that these arguments are mostly in different units from each other:
risk.fraction: fraction of variance (by default)
positions: monetary value
upper.trade: units (shares, contracts, …)