In [2]:
import sys

sys.path.insert(0, "../../")
#  演示必要的准备代码,使用该库时不需重复此单元格命令
In [3]:
import xalpha as xa
import pandas as pd

本文将分析大陆公募基金市场中和石油商品相关的基金,考察其相关性和可替代性

In [4]:
hb = xa.fundinfo("162411")  # 华宝油气
gf = xa.fundinfo("162719")  # 广发石油
ha = xa.fundinfo("160416")  # 华安石油
nf = xa.fundinfo("501018")  # 南方原油
yfd = xa.fundinfo("161129")  # 易方达原油
js = xa.fundinfo("160723")  # 嘉实原油
In [5]:
oilcomp = xa.evaluate(hb, gf, ha, nf, yfd, js)
In [6]:
oilcomp.v_correlation()
Out[6]:

观察上述的相关系数图,可以看到高关联的基金自动分成两个区。三个跟踪原油期货的基金关联极高。同时三个在美股为主跟踪石油产业企业股票指数的基金(对应指数不同)关联极高。另一方面,两者之间关联并没有特别高。像经常宣传和原油价格走势关联很高的华宝油气,其关联系数也只有 0.67 左右,并不是很高。这种跟踪意义不大,下面不同基金的净值图将这个问题表现的更明显。 如果非想持有石油股票指数来减少原油期货换仓损失的话,华安石油相比华宝油气具有更高的关联性,相关系数在 0.73 左右,高于另两个石油股票基金。

In [7]:
oilcomp.v_netvalue()
Out[7]:

可以看到三个追踪原油期货的基金,走势几乎完全一致,在两年多的时间中产生的误差很有限。 奇怪的是,在这段区间石油价格有所回升,同时美股一直运行在牛市,但主力在美股的石油企业的股票走势还比不上原油价格本身,尤其是华宝油气表现极差。也就是说,美股里这些企业估值在不断走低,对应了大家的夕阳产业预期。

  • 华宝油气:0.15+1.28, 标普石油天然气上游股票指数
  • 华安石油: 0.12+1.28, 标普全球石油指数
  • 广发石油: 0.39 亿,规模低于清盘线,请谨慎申购, 0.12+1.3, 道琼斯美国石油开发与生产指数

  • 易方达原油: 0.12+1.25,标普高盛原油商品指数

  • 南方原油: 0.12+1.28, 60%WTI原油价格收益率 + 40%BRENT原油价格收益率
  • 嘉实原油: 0.12+1.28,100%WTI原油价格收益率
In [10]:
for fund in oilcomp.fundobjs:
    print(fund.name, fund.algorithm_volatility())
华宝标普油气上游股票 0.31330039728004055
广发道琼斯石油指数人民币A 0.23449795919975377
华安标普全球石油指数 0.1684688810075437
南方原油A 0.23465224682648175
易方达原油A类人民币 0.2244510474007535
嘉实原油(QDII-LOF) 0.22860537822326174

大多数人投资石油基金并不是为了长期价值投资,而是为了做波段,因此波动率越高越好。由此可以看出,华宝油气是波动最大的。

我们现在研究下原油基金的换仓损耗到底有多高,首先爬取过去一年的 WTI 原油期货价格日线数据

In [35]:
import requests
import datetime as dt
In [62]:
r = requests.get(
    "https://cn.investing.com/common/modules/js_instrument_chart/api/data.php?pair_id=8849&pair_id_for_news=8849&chart_type=area&pair_interval=86400&candle_count=120&events=yes&volume_series=yes&period=1-year",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
        "Referer": "https://cn.investing.com/commodities/crude-oil",
        "Host": "cn.investing.com",
        "X-Requested-With": "XMLHttpRequest",
    },
)
In [64]:
tz_utc = dt.timezone(dt.timedelta(hours=0))
date = []
netvalue = []
for line in r.json()["candles"]:
    date.append(dt.datetime.fromtimestamp(line[0] / 1000, tz_utc).replace(tzinfo=None))
    netvalue.append(line[1])
df = pd.DataFrame(data={"date": date, "netvalue": netvalue})
df
Out[64]:
date netvalue
0 2018-08-24 68.72
1 2018-08-27 68.87
2 2018-08-28 68.53
3 2018-08-29 69.51
4 2018-08-30 70.25
5 2018-08-31 69.80
6 2018-09-02 69.92
7 2018-09-03 70.12
8 2018-09-04 69.87
9 2018-09-05 68.72
10 2018-09-06 67.77
11 2018-09-07 67.75
12 2018-09-10 67.54
13 2018-09-11 69.25
14 2018-09-12 70.37
15 2018-09-13 68.59
16 2018-09-14 68.99
17 2018-09-17 68.91
18 2018-09-18 69.85
19 2018-09-19 71.12
20 2018-09-20 70.80
21 2018-09-21 70.78
22 2018-09-24 72.08
23 2018-09-25 72.28
24 2018-09-26 71.57
25 2018-09-27 72.12
26 2018-09-28 73.25
27 2018-10-01 75.30
28 2018-10-02 75.23
29 2018-10-03 76.41
... ... ...
234 2019-07-15 59.58
235 2019-07-16 57.62
236 2019-07-17 56.78
237 2019-07-18 55.30
238 2019-07-19 55.63
239 2019-07-22 56.22
240 2019-07-23 56.77
241 2019-07-24 55.88
242 2019-07-25 56.02
243 2019-07-26 56.20
244 2019-07-29 56.87
245 2019-07-30 58.05
246 2019-07-31 58.58
247 2019-08-01 53.95
248 2019-08-02 55.66
249 2019-08-05 54.69
250 2019-08-06 53.63
251 2019-08-07 51.09
252 2019-08-08 52.54
253 2019-08-09 54.50
254 2019-08-12 54.93
255 2019-08-13 57.10
256 2019-08-14 55.23
257 2019-08-15 54.47
258 2019-08-16 54.87
259 2019-08-19 56.21
260 2019-08-20 56.34
261 2019-08-21 55.68
262 2019-08-22 55.35
263 2019-08-23 53.95

264 rows × 2 columns

我们还需要额外爬取人民币美元汇率数据用于比较

In [81]:
r = requests.get(
    "https://cn.investing.com/common/modules/js_instrument_chart/api/data.php?pair_id=2111&pair_id_for_news=2111&chart_type=area&pair_interval=86400&candle_count=120&events=yes&volume_series=yes&period=1-year",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
        "Referer": "https://cn.investing.com/commodities/currencies/usd-cny",
        "Host": "cn.investing.com",
        "X-Requested-With": "XMLHttpRequest",
    },
)
In [82]:
tz_utc = dt.timezone(dt.timedelta(hours=0))
date = []
netvalue = []
for line in r.json()["candles"]:
    date.append(dt.datetime.fromtimestamp(line[0] / 1000, tz_utc).replace(tzinfo=None))
    netvalue.append(line[1])
usdf = pd.DataFrame(data={"date": date, "netvalue": netvalue})
usdf
Out[82]:
date netvalue
0 2018-08-24 6.8070
1 2018-08-27 6.8156
2 2018-08-28 6.8030
3 2018-08-29 6.8213
4 2018-08-30 6.8445
5 2018-08-31 6.8315
6 2018-09-03 6.8228
7 2018-09-04 6.8442
8 2018-09-05 6.8305
9 2018-09-06 6.8355
10 2018-09-07 6.8438
11 2018-09-10 6.8556
12 2018-09-11 6.8730
13 2018-09-12 6.8606
14 2018-09-13 6.8448
15 2018-09-14 6.8690
16 2018-09-17 6.8570
17 2018-09-18 6.8616
18 2018-09-19 6.8483
19 2018-09-20 6.8468
20 2018-09-21 6.8571
21 2018-09-24 6.8571
22 2018-09-25 6.8665
23 2018-09-26 6.8786
24 2018-09-27 6.8902
25 2018-09-28 6.8689
26 2018-10-01 6.8689
27 2018-10-02 6.8689
28 2018-10-03 6.8689
29 2018-10-04 6.8689
... ... ...
231 2019-07-15 6.8777
232 2019-07-16 6.8762
233 2019-07-17 6.8736
234 2019-07-18 6.8800
235 2019-07-19 6.8822
236 2019-07-22 6.8811
237 2019-07-23 6.8792
238 2019-07-24 6.8725
239 2019-07-25 6.8726
240 2019-07-26 6.8792
241 2019-07-29 6.8934
242 2019-07-30 6.8845
243 2019-07-31 6.8841
244 2019-08-01 6.8986
245 2019-08-02 6.9405
246 2019-08-05 7.0508
247 2019-08-06 7.0264
248 2019-08-07 7.0602
249 2019-08-08 7.0451
250 2019-08-09 7.0624
251 2019-08-12 7.0582
252 2019-08-13 7.0435
253 2019-08-14 7.0244
254 2019-08-15 7.0340
255 2019-08-16 7.0428
256 2019-08-19 7.0507
257 2019-08-20 7.0605
258 2019-08-21 7.0632
259 2019-08-22 7.0836
260 2019-08-23 7.0960

261 rows × 2 columns

In [85]:
df.iloc[-2].netvalue * usdf.iloc[-2].netvalue / df.iloc[0].netvalue / usdf.iloc[
    0
].netvalue  # 一年真实的油价变化(人民币计价)
Out[85]:
0.8381712364505961
In [86]:
fund = js
float(fund.price[fund.price["date"] == "2019-08-22"].netvalue) / float(
    fund.price[fund.price["date"] == "2018-08-24"].netvalue
)
Out[86]:
0.8154402005603893

一年大约落后跟踪基准 2.7%, 考虑到嘉实原油一年 1.28% 的管理费,大约还会跑输 1.5% 左右。特别是,这一年,美元走强,基金又有一定现金份额来抵消石油价格下降,因此真实跑输大于 1.5%。其中大部分没意外,都是期货换仓的损失。所以粗略估计,每年的持仓额外成本在 1 到 2 个百分点。

由于另两个原油基准宣称的基准略有不同,以下列出仅供参考:

In [87]:
fund = yfd
float(fund.price[fund.price["date"] == "2019-08-22"].netvalue) / float(
    fund.price[fund.price["date"] == "2018-08-24"].netvalue
)
Out[87]:
0.8271919660100425
In [88]:
fund = nf
float(fund.price[fund.price["date"] == "2019-08-22"].netvalue) / float(
    fund.price[fund.price["date"] == "2018-08-24"].netvalue
)
Out[88]:
0.8347042694868781
In [ ]: