ふと株価指標を見て気づいたのですが、米国株指標であるS&P500に連動するETFの年初来リターン(2018年1月1日から2018年12月10日午前の段階)が0.15%でした。一方でS&P500を指標にしたレバレッジファンドSPXLの年初来リターンは-12%でした。思ったよりもリターンに差がでたな、と思い検証してみることにしました。twitterで一連のツイートをつぶやきましたが記事として残しておきます。
レバレッジのファンドのリターンをどう考えるか?
S&P500連動ETFであるIVVと、3倍のレバレッジをかけたSPXLのリターンは別に常に3倍になるわけではないです。3倍の値動きをするのがある一日の値動きについてだからです。なのでIVVのリターンが0%だからといってSPXLのリターンも0%にはなるわけではないのは当たり前です。
以前取り上げたように、値動きが何倍かになることによって、基準となる指標に劣後しているように見えることがあるのがレバレッジファンドの特性です。(以下の記事では配当調整済みのリターンを解析に使用しているので配当はすべて内部で再投資されていると考えてください。)

なので、現在のIVVとSPXLのリターンの差の12%を、1,(レバレッジを掛けたこと自体が原因のズレ)と、2,(レバレッジファンドの経費や利子)、3,(誤差)の3つの要素に分解して考えてみます。
1.は実際のIVVのリターンを3倍にした仮想のファンドを作ってやれば求めることができます。計算してみるとその仮想ファンド(ideal SPXL)の年初来リターンは-8.7%でした。原資産がボックス相場を行ったり来たりしている間にレバレッジの激しい値動きにさらされてレバレッジファンドのリターンは目減りしてしまいます。結構激しいですね。この幅は値動きが激しいほど下落が大きくなりますが、今年のS&P500の年率換算リスクは16.0%でした。
3つのファンド:IVV、ideal SPXL、SPXLのリターンを比較してみましょう。
赤と緑は黒のIVVよりも激しく値動きします。赤は理想的に3倍の値動きをするファンドです。緑は赤よりも目に見えて劣後しているのがわかりますね。この赤と緑の差がレバレッジファンドにかかるコストなどが原因と考えて良さそうです。
レバレッジファンドのコスト

レバレッジファンドにかかるコストについても以前考察しました。手数料や金利分はリターンから目減りすることがわかっています。実際に理想的な動きをするSPXLと実際のSPXLのリターンを毎日比べたものをプロットしてみるとこんな風になります。
ギザギザしてますね。下に行くと実際のSPXLのリターンが理想的な値動きよりも少なかったことを表しています。7月に-0.5%も劣後しているのは原因はわかりませんがかなり大きな乖離です。
月ごとに乖離幅を平均をとって見ても、6月は1日あたり-0.005%ですが7月は-0.04%も乖離しています。ただ、一貫して下に乖離しており、実際のSPXLは相変わらずコストによる減価を受けていることがわかります。
コストによる減価を正確に見積もるのは難しいですが、12%-8.7%=3.3%としても良いですし、実際の乖離幅からコストを計算すると5.6%程度にも相当することがわかりました。
SPXLの手数料が年率約1%程度なので5.6-1 = 4.6%分はおそらく金利コスト(と取引で生じた誤差)と考えられます。原資産の200%を借り入れているとなると、4.6 /2 = 2.3%/年程度の金利コストと見積もられますが、まあまあ妥当な数字じゃないでしょうか。
SPXLの設計から予想される以上にリターンを押し下げている要因は特に見当たらないと思います。
レバレッジにより変化するリターン
今年1年でS&P500は平均して1日あたりほぼ0.0%の値動きをしたことになりますが、もちろん上がった日も下がった日も有るので分散としてリスクは年率16.0%あったことになります。
この条件で値動きをした場合、どの程度の確率で、どの程度のリターンが見込まれるでしょうか?乱数を発生(正規分布)させて、10万年分シミュレーションを行ってみました。
レバレッジを掛けないとき、期待値(mean)は0.6%/年のリターンでした。順位にしてちょうど真ん中に相当する中央値(median)は-0.6%です。リターンをヒストグラムにすると0%を中心にしてほぼ左右対称な形に裾野が広がります。
しかし、3倍のレバレッジをかけたとき、期待値こそ2%/年ですが、中央値は-9%/年になりました。平均的には3倍のリターンになりますが、上位半分の人で実は結構損することになります。分布も山頂が左によって右の裾野が大きく広がります。
一番儲からなかった人(0%)から一番儲かった人(100%)までを並べてみると(75%であれば、上位25%の人)、レバレッジをかけると分布がかなり広がることがわかりますね。
上がレバレッジがかかっていないものです。トップが+95%のリターン、上から25%の人は10.7%のリターン。真ん中の人は-0.63%、下25%は-10.8%のリターンです。下のレバレッジがかかったリターンのトップは+686%ものリターンです。上25%でも26%ものリターンを出しています。しかし真ん中は-8.88%と悪く、下25%の人は-34%とかなり悪いリターンになります。
原資産のリターンに対してレバレッジファンドのリターンをプロットしてみました。原資産のリターンが低いとレバレッジファンドのリターンはいまいちですが、原資産のリターンが高かった場合レバレッジは3倍以上のリターンをもたらします。
横軸がレバレッジなし、縦軸はレバレッジありです。
少し見にくいので原資産とレバレッジファンドのリターンが均等になる辺りを拡大してみます。黒い線はy = xのグラフです。緑とオレンジの線が原資産のリターンに対するレバレッジファンドのリターンを示しています。
この図から分かる通りレバレッジファンドのリターンが0%(y軸が1.0のオレンジの点です)になるときに対応する原資産のリターンは、4.5%必要でした。これは変動による損失と金利コストなどを含めた計算です。レバレッジをかけることでもプラスのリターンを得るためには4-5%程度のリターンが必要だし、レバレッジファンドが原資産のリターンを上回るのは(黒い線とカラフルな線の交点)原資産のリターンは7-8%は必要になります。
とりあえず、今年のレバレッジファンドの成績は散々ですが、これは予測された結果と大きくは変わらないということがわかりました。人為的なエラーなどはなさそうです。
使用したコード
解析はRを使いました。コードは以下を参考にしてください。
#### Setting #### | |
library(lubridate) | |
library(quantmod) | |
library(PerformanceAnalytics) | |
library(stringr) | |
library(ggplot2) | |
#### Functions #### | |
levETF_plot <- function(lev, ind, leverage, start, end){ | |
start_cal <- max(index(ind)[1], index(lev)[1]) + 1 | |
#### Calculate Return ### | |
lev_return = periodReturn(lev[,6], period = "daily", subset=paste(start_cal, "::", sep = ""), type = 'arithmetic') | |
ind_return = periodReturn(ind[,6], period = "daily", subset=paste(start_cal, "::", sep = ""), type = 'arithmetic') | |
#### Analysis, ∆LevETF = ΔIndETF * 3 + (Slippage) ### | |
real = lev_return | |
ideal = ind_return * leverage | |
delta = (real - ideal) * 100 | |
#### Daily Slippage ### | |
par(ps = 10) | |
main_title = str_c(leveragedETF, " Daily Slippage (", leveragedETF, " - ", indexETF," * ",leverage,"%)") | |
chartSeries(delta, minor.ticks=FALSE, type="l", | |
theme = chartTheme("white", up.col="black"), | |
name = main_title, ylab='Residuals', xlab='Date', | |
yrange = c(min(delta), max(delta))) | |
daily_slippage_mean = mean(delta) # 1日の平均 | |
daily_abs_slippage = mean(sqrt(delta ^ 2)) # 1日の平均 | |
yearly_slippage <- (prod(1+0.01*delta[str_c(end-365, '::', end)])-1)*100 #直近1年のスリップ | |
#### Daily slippage (monthly mean) ### | |
delta_monthly <- apply.monthly(delta,mean) | |
month_title = str_c(leveragedETF, " Daily Slippage (Monthly mean)(%)") | |
chartSeries(delta_monthly, minor.ticks=FALSE, type="l", | |
theme = chartTheme("white", up.col="black"), | |
name = month_title, | |
ylab='slippage', xlab='Date', | |
yrange = c(min(delta_monthly), max(delta_monthly))) | |
return(delta) | |
} | |
prodSlip <- function(delta){ | |
slip <- prod(1+delta/100) - 1 | |
return(slip * 100) | |
} | |
#### Input #### | |
end <- as.Date("2018-12-09") | |
start <- as.Date("2018-01-01") | |
leveragedETF <- c("SPXL") | |
leverage <- 3 | |
indexETF <- "IVV" | |
#### function #### | |
#### Fetch Stock Data ### | |
lev = getSymbols(leveragedETF[1], src = 'yahoo', auto.assign = FALSE, warnings = FALSE, from=start, to=end) | |
ind = getSymbols(indexETF, src = 'yahoo', auto.assign = FALSE, warnings = FALSE, from=start, to=end) | |
#### Calculate Return ### | |
lev_return = periodReturn(lev[,6], period = "daily") | |
ind_return = periodReturn(ind[,6], period = "daily") | |
#### ideal SPXL return #### | |
ideal = ind_return * leverage | |
mergedReturns <- merge.xts(ind_return, ideal, lev_return) | |
colnames(mergedReturns) <- c("IVV", 'Ideal SPXL', 'SPXL') | |
charts.PerformanceSummary(mergedReturns, main='S&P500 ETFs') | |
Return.cumulative(mergedReturns) | |
#### Analysis, ∆LevETF = ΔIndETF * 3 + (Slippage) ### | |
real = lev_return | |
delta = (real - ideal) * 100 | |
delta <- levETF_plot(lev, ind, 3, start, end) | |
slip <- apply.yearly(delta, prodSlip) | |
print(slip) | |
chartSeries(delta, minor.ticks=FALSE, type="l", | |
theme = chartTheme("white", up.col="black"), | |
name = "SPXL daily slippage", | |
ylab='slippage', xlab='Date', | |
yrange = c(min(delta), max(delta))) | |
mean(delta) | |
#### Simulation #### | |
mean(ind_return) | |
sd(ind_return) | |
StdDev.annualized(ind_return) | |
n <- 100000 | |
y <- rep(1, n) | |
z <- rep(1, n) | |
for(i in 1:252){ | |
x <- rnorm(n, mean = 1+mean(ind_return), sd = sd(ind_return)) | |
y <- y * x | |
z <- z * ((x-1)*3+1+mean(delta)/100) | |
} | |
hist(y, breaks = seq(from = round(min(y)-0.1, digits = 1), to = round(max(y)+0.1, digits=1), by = 0.05), main = "Yearly estimate return of S&P500") | |
mean(y) | |
median(y) | |
hist(z, breaks = seq(from = round(min(z)-0.1, digits = 1), to = round(max(z)+0.1, digits=1), by = 0.05), main = "Yearly estimate return of Leveraged S&P500") | |
mean(z) | |
median(z) | |
signif((quantile(y,c(0,0.1,0.25,0.5,0.75,0.9,1))-1)*100,3) | |
signif((quantile(z,c(0,0.1,0.25,0.5,0.75,0.9,1))-1)*100,3) | |
scatter.smooth(y,z) | |
lm(z~y) | |
df <- data.frame(y = y, z = z) | |
df <- df[order(df$z),] | |
df[df$z >0.9999 & df$z<1.0001,] | |
yzcolor <- ifelse(df$y<df$z, 1, 0) | |
df$color <- as.factor(yzcolor) | |
ggplot(df, aes(x = y, y = z, color = color)) + | |
geom_point() + | |
geom_abline(slope = 1, intercept = 0) + | |
xlab("Original Asset Return") + | |
ylab('Leveraged Asset Return') + | |
xlim(c(0.8, 1.3)) + | |
ylim(c(0.8, 1.3)) |
コメント
いつも大変興味深い記事を誠にありがとうございます.今回のSPXLのコストの記事は自分も大変気になっていたところでとてもおもしろかったです.
一つ気になることがありまして,質問させて頂きたいのですが,SPXLの場合,もし配当がでなければ(今年は0.6%程度配当が出てしまっておりましたが,),理想的な値動きをするSPXLと実際のSPXLの差(=コスト)は「配当×3-金利×2-Expense ratio(約1%)」と認識しておりました.理論的には先物価格には短期金利と将来得られるであろう配当が組み込まれているため,「実際の乖離幅からコストを計算すると5.6%」となると,ほぼ配当部分がなくなっているように見受けられ,その部分が気になってしまっております.ただ,実際の差の単純計算の-3.3%ですと,内訳として,「 配当(1.6~1.8%)x3-分配金(0.6%x1回)-expense ratio 1% -金利(2.3%)x2から計算すると」-2.0~-1.4%程度とこれでもやはり1%程度余分にした押ししてるのかな?と考えております.実際は今年はFF金利の段階的上昇や株価の上下に伴う配当利回りの変化もあるため,1%程度は誤差なのかなと思っておりますが,配当金の行方がどうなのかな?と少し気になってしまいました.長文誠に失礼致しました.
いつもおもしろい記事をありがとうございます!
コメントありがとうございます。本文中に明記するのを忘れてしまっていましたが、記事内でのリターンの計算では配当調整済みリターンを使用しています。なのでETF内部で配当分は再投資され、分配金による値下がりも無いものとお考えください。
つまり、リターン = キャピタル・ゲイン + 配当分(分配金)に相当しています。
計算では乖離幅を幾何的に合わせていったものが5.6%/年の影響、理想的な値動きからのズレが3.3%/年なので解釈どちらを採用するかは難しいところで決めきれませんでした。おっしゃる通り利率も連続的に変化しているので何%に設定するのかもはっきりわかりません。ただ、配当分(+分配金)がリターンに含まれていることを考えると、差分はexpense ratioと金利の合計です。これらが日割り計算でリターンから引かれている仮定で年間リターンに与える影響を計算するとほぼ理論的に導かれるのと同じ5.6%/年のコストになっていたのでまあまあ妥当かと思っています。
お返事ありがとうございます.
丁寧にご説明頂きありがとうございます.リターンが配当調整済みリターンであることを勘違いしてりました,すいません.おかけさまで府におちました.この中身の部分も一度説明を受けると納得なのですが,何も情報がない段階で解析して導くのはなかなかに大変かなと思います.
いつも興味深い記事をありがとうございます.
また,丁寧にお返事を頂きありがとうございました.
今後も応援しています!