レバナス vs QLD
はてブロはカス
何故か画像が表示されないのでこっち見て→ https://github.com/omi-key/misc/blob/master/QLD/%E3%83%AC%E3%83%90%E3%83%8A%E3%82%B9%20vs%20QLD.ipynb
.
.
.
.
.
.
.
本編
昨今のコロナ禍も目じゃなく伸びている株式インデックスにアメリカ株の NASDAQ100 がある。
だいたいGAFAMとテスラとzoomとなんかそこら辺の強そうな株が突っ込まれているので、日経平均だの S&P 500 だのを尻目にぐんぐん伸びている。
ところで ETF 界には、各インデックスに「日々の値動きの x 倍 (-3 <= x <= 3)を目指す」ような設計をしたやつが結構いる。先物取引を利用してなんやかんやするのだが、昨今の低金利でキャリーコストが下がっているせいもあってめちゃくちゃに流行っている。
当然 NASDAQ100 に正のレバレッジを掛けた商品を買いたいのだが、如何せん日本から直接は買えない。(S&P 500 のレバレッジ ETF は買えたりする)
しかしここに iFreeレバレッジ NASDAQ100 、通称レバナスなる投信があって、これはドルベースで NASDAQ100 指数の 2 倍を目指して運用されているような商品である。じゃあこれは日本で買えない QLD の替わりになるんじゃないか、ということで QLD 比でのパフォーマンスを調べてみた。
免責事項 - Disclaimer
本記事に記載されるいかなる情報も、投資への勧誘、特定の商品の勧誘や売買の推奨、特定商品、銘柄および株式指数その他投資対象の上昇または下落、あるいは将来の運用成果について示唆あるいは保証することを目的としたものではありません。
本記事は「現状有姿のまま」で提供します。筆者は可能な限り正確性を保つ努力を行いましたが、本記事の記述内容が現に正確またはいかなる読者の投資目的に適合することを保証するものではなく、筆者は本記事についての一切の責任を負いません。また本記事に含まれる情報もしくは内容を利用することで直接・間接的に生じた損失・損害に対し筆者が一切責任を負わないことについて、読者は本記事の閲覧を継続することで同意したものとします。
データ元
- Yahoo! Finance
- 大和アセットマネジメント
それぞれデータDLボタンがあるので押して適当にリネームして配置した。
方針
日本の投信のうち主に海外資産を運用する商品は、時差を考慮して
という流れになっている。つまり、日本時間で x 日の基準価額はアメリカ時間 x-1 日の終値に依存する。
まあ日米ともに祝日があるはずだけれど、今回のコードでは深く考えずに、日本時間の基準日の直前営業日における終値を用いて QLD の米ドル・日本円価格を算出した。
import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns
データ読み込み
レバナス
csv ははやく encoding が UTF-8 のもののみ valid として欲しい。
levnas = pd.read_csv("rev_NASDAQ.csv", encoding="SHIFT-JIS")
用いる終値、基準日を取り出しておく。
ついでに後ほど求める QLD 価格(usd, jpy) のカラムを用意する。
levnas["close"] = levnas["基準価額"] levnas["date"] = pd.to_datetime(levnas["基準日"], format="%Y%m%d") levnas["qldusd"] = 0 levnas["qldjpy"] = 0 levnas
基準日 | 基準価額 | 前日比 | 純資産総額 | 直近決算日 | 直近分配金 | 分配金再投資基準価額 | close | date | qldusd | qldjpy | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 20181019 | 10001.0 | 0 | 300033250 | 0 | 0 | 10001 | 10001.0 | 2018-10-19 | 0 | 0 |
1 | 20181022 | 9998.0 | -3 | 299937512 | 0 | 0 | 9998 | 9998.0 | 2018-10-22 | 0 | 0 |
2 | 20181023 | 10132.0 | 134 | 303965761 | 0 | 0 | 10132 | 10132.0 | 2018-10-23 | 0 | 0 |
3 | 20181024 | 10090.0 | -42 | 302696469 | 0 | 0 | 10090 | 10090.0 | 2018-10-24 | 0 | 0 |
4 | 20181025 | 9250.0 | -840 | 277496525 | 0 | 0 | 9250 | 9250.0 | 2018-10-25 | 0 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
425 | 20200727 | 18468.0 | -1427 | 13454015575 | 20191018 | 0 | 18468 | 18468.0 | 2020-07-27 | 0 | 0 |
426 | 20200728 | 19227.0 | 759 | 14006937427 | 20191018 | 0 | 19227 | 19227.0 | 2020-07-28 | 0 | 0 |
427 | 20200729 | 18743.0 | -484 | 13900493329 | 20191018 | 0 | 18743 | 18743.0 | 2020-07-29 | 0 | 0 |
428 | 20200730 | 19218.0 | 475 | 14477773611 | 20191018 | 0 | 19218 | 19218.0 | 2020-07-30 | 0 | 0 |
429 | 20200731 | 19649.0 | 431 | 14811577362 | 20191018 | 0 | 19649 | 19649.0 | 2020-07-31 | 0 | 0 |
430 rows × 11 columns
QLD, USD/JPY
qld = pd.read_csv("QLD.txt") qld.set_index("Date") usdjpy = pd.read_csv("USDJPY.txt") usdjpy.set_index("Date")
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
1996-10-30 | 114.370003 | 114.480003 | 113.610001 | 114.180000 | 114.180000 | 0.0 |
1996-10-31 | NaN | NaN | NaN | NaN | NaN | NaN |
1996-11-01 | 113.500000 | 113.500000 | 113.500000 | 113.500000 | 113.500000 | 0.0 |
1996-11-04 | 113.279999 | 113.980003 | 112.949997 | 113.879997 | 113.879997 | 0.0 |
1996-11-05 | 113.709999 | 114.330002 | 113.449997 | 114.250000 | 114.250000 | 0.0 |
... | ... | ... | ... | ... | ... | ... |
2020-07-27 | 105.956001 | 106.046997 | 105.121002 | 105.992996 | 105.992996 | 0.0 |
2020-07-28 | 105.291000 | 105.679001 | 104.958000 | 105.261002 | 105.261002 | 0.0 |
2020-07-29 | 105.110001 | 105.227997 | 104.800003 | 105.107002 | 105.107002 | 0.0 |
2020-07-30 | 105.015999 | 105.288002 | 104.912003 | 105.031998 | 105.031998 | 0.0 |
2020-07-31 | 104.667000 | 105.795998 | 104.198997 | 104.682999 | 104.682999 | 0.0 |
6198 rows × 6 columns
Date を key にしてマージ。
QLD の Adj. Close と USD/JPY の Close を掛け合わせることで JPY での終値を算出する。
配当などを調整した後の価格が Adj. Close らしい。
qldusd = pd.merge(qld, usdjpy, on="Date") qldusd["close_JPY"] = qldusd["Adj Close_x"] * qldusd["Close_y"] qldusd[["Date", "Adj Close_x", "close_JPY"]]
Date | Adj Close_x | close_JPY | |
---|---|---|---|
0 | 2006-06-21 | 7.940834 | 911.885664 |
1 | 2006-06-22 | 7.753991 | 900.083291 |
2 | 2006-06-23 | 7.730908 | 900.960026 |
3 | 2006-06-26 | 7.759483 | 901.807122 |
4 | 2006-06-27 | 7.469331 | 868.832582 |
... | ... | ... | ... |
3548 | 2020-07-27 | 162.600006 | 17234.461786 |
3549 | 2020-07-28 | 158.559998 | 16690.184267 |
3550 | 2020-07-29 | 162.229996 | 17051.508514 |
3551 | 2020-07-30 | 163.860001 | 17210.543297 |
3552 | 2020-07-31 | 169.679993 | 17762.610538 |
3553 rows × 3 columns
あきらかにこんなにいらないのと、現状 Date カラムが str なので datetime へ変換しておく。
qldjpy = qldusd.loc[3000:, ["Date","Adj Close_x", "close_JPY"]] qldjpy["Date"] = pd.to_datetime(qldjpy["Date"], format="%Y-%m-%d") qldjpy
Date | Adj Close_x | close_JPY | |
---|---|---|---|
3000 | 2018-05-22 | 83.026443 | 9214.108342 |
3001 | 2018-05-23 | 84.413208 | 9346.736700 |
3002 | 2018-05-24 | 84.333389 | 9265.625369 |
3003 | 2018-05-25 | 84.512985 | 9238.283078 |
3004 | 2018-05-29 | 83.754745 | 9161.847801 |
... | ... | ... | ... |
3548 | 2020-07-27 | 162.600006 | 17234.461786 |
3549 | 2020-07-28 | 158.559998 | 16690.184267 |
3550 | 2020-07-29 | 162.229996 | 17051.508514 |
3551 | 2020-07-30 | 163.860001 | 17210.543297 |
3552 | 2020-07-31 | 169.679993 | 17762.610538 |
553 rows × 3 columns
マージ
競プロ民とは思えぬ脳死 O(N2)
430 くらいなら実用上問題ないのでセーフ
for i in range(430): keydate = levnas.loc[i, "date"] j = 3000 while qldjpy.loc[j, "Date"] < keydate: j += 1 levnas.loc[i, "qldusd"] = qldjpy.loc[j-1, "Adj Close_x"] levnas.loc[i, "qldjpy"] = qldjpy.loc[j-1, "close_JPY"]
プロット
QLD(usd)
レバナスの商品設計としてはドルベースの NASDAQ100 (の 2 倍)が基準なので、まずはそのままドルベースの QLD と比較する。
だいたいここ 2 年くらいドル円が 110 円くらいだった気がするので 110 を掛けてプロットしてみる
plt.plot(levnas["date"], levnas["close"], label="leveraged_NASDAQ") plt.plot(levnas["date"], levnas["qldusd"] * 110, label="QLD(USD)") plt.legend()
<matplotlib.legend.Legend at 0x7f2ede4dd9d0>
[f:id:omi_ut:20200803000111p:plain]
よくわからないのでおとなしく比を取る。
plt.plot(levnas["date"], levnas["close"]/levnas["qldusd"])
[<matplotlib.lines.Line2D at 0x7f2ede3d6fa0>]
[f:id:omi_ut:20200803000121p:plain]
設定当初は 117 くらいだった比がコロナ前 114 までじわじわと落ち込み、その直後急に 118 程度で安定するようになっている。
これはレバナスが為替ヘッジをしているためであると考えられる。コロナ前は日米金利差がそこそこあったのでヘッジコストが発生していたが、アメリカの金利もゼロになったのでヘッジコストがほぼ無になり、この比が安定したようだ。たぶん。
じゃあなんで為替ヘッジなんてするんですかというと、先物取引の都合上ファンド資金はそのまま証拠金になり、ドルベースの差金決済取引になるので本来差金分しか為替影響を受けない中途半端な状態になってしまう。であれば、ということでいっそまるごと為替ヘッジをしているのだと思う。
たぶん。
QLD(jpy)
ところで普通にアメリカ ETF 買った時に為替ヘッジなんてしませんよね? ということで日本円ベースで比較
plt.plot(levnas["date"], levnas["close"], label="leveraged_NASDAQ") plt.plot(levnas["date"], levnas["qldjpy"], label="QLD") plt.legend()
<matplotlib.legend.Legend at 0x7f2ede3b62b0>
[f:id:omi_ut:20200803000131p:plain]
plt.plot(levnas["date"], levnas["close"]/levnas["qldjpy"])
[<matplotlib.lines.Line2D at 0x7f2ede3833a0>]
ドル円の動きに従って結構跳ねているが、コロナ以降はQLD比 1.1 と今までよりも高値圏で安定しているように見られる。
当然円高が進めばその分為替ヘッジを行うレバナス有利な戦いになる。
ここまでのまとめ
ヘッジコスト (≒金利差) が発生しない間においては、レバナスは完全に QLD 互換と言ってよさそう。
結論
大和アセットマネジメントははやく TQQQ 互換を出して やくめでしょ