这篇文章介绍了Fama 三因子和Carhat 四因子,主要是在介绍Fama三因子,因为Carhat四因子,只是三因子的拓展。
并且,计算方法是我对两篇文章的学习注解,可以先去看原文章。

本篇文章学习参考资料有:
[1] 刘媛媛. 中国股票市场的有效性实证研究[D].西南财经大学,2012.
[2] 张庄昊. 改进动量因子的四因子量化投资方案策划[D].上海师范大学,2018.
[3] Carhart四因子模型A股实证(附源码)
[4] Fama-French三因子回归A股实证(附源码)

先唠叨一下自己的一些观点:
我的理解是这些模型设计的初中是为了解释投资组合(股票)的收益率来源。
如:Markowtiz(1952)投资组合理论认为收益率是对风险的补充;
Sharp(1964)、Lintner(1965)和Mossin(1966)提出的资本资产定价模型(CAPM),认为收益率对系统风险的补充;
Fama和French(1993)提出三因子模型,是认为收益率来自于市值规模、账面市值比、市场风险(系统风险)
Carhart 提出四因子模型,是认为收益率来自市值规模、账面市值比、市场风险(系统风险)以及动量效应
本人理解模型本质都是探讨收益率来自于什么,或者说是受何因素影响。认识有限,若有错误,欢迎指正~

好啦,现在进入正文~

Fama三因子和Carhat 四因子的介绍和计算

  • 1 Fama三因子
    • 1.1 Fama三因子的出现
      • 1.1.1 投资组合理论
      • 1.1.2 资本资产定价模型
      • 1.1.3 Fama三因子出现
    • 1.2 Fama三因子的介绍
      • 1.2.1 核心观点
      • 1.2.2 原理及模型
    • 1.3 Fama三因子的计算
  • 2 Carhat 四因子模型的介绍和计算
    • 2.1 Carhat四因子模型的介绍
      • 2.1.1 Carhat四因子的引出
      • 2.1.2 Carhat四因子的模型
      • 2.1.3 与Fama三因子的差别
    • 2.2 Carhat 四因子的计算

1 Fama三因子

1.1 Fama三因子的出现

1.1.1 投资组合理论

Markowtiz(1952)投资组合理论核心观点:1)提出利用证券投资收益率的方差作为衡量风险的指标;2)将风险分为两类,一类是通过多样的资产组合可分散消除的风险,称为非系统风险;另一类是不能用资产组合分散的风险称为系统风险;2)风险水平确定的情况下来选择具有最高收益率的投资组合集合,或者在给定收益率水平下,选择具有最小风险的投资组合集合。

1.1.2 资本资产定价模型

Sharp(1964)、Lintner(1965)和Mossin(1966)提出资本资产定价模型(CAPM)核心观点:1)股票的预期收益率与其风险成正相关关系,投资股票的收益被视为投资者投资某股票所承担的风险的补偿;2)风险资产的收益等于无风险资产收益加上风险升水。即高风险伴随高收益,系统风险用β来衡量;3)β是股票收益对整个市场组合收益的影响(是衡量系统性风险的指标),可作为单个股票收益率变动的敏感性指标。4)换言之,在有效资产组合中,非系统风险能被多样化分散投资消除,而系统风险不会因为投资的多样化而被分散消除,因此资产组合的期望收益率仅与资产组合的系统风险相关


过于严苛的假设条件后的发展:1)无风险资产不存在时的零资本资产定价模型;2)考虑税收的资本资产定价模型;3)跨期的资本资产定价模型;4)套利定价理论。
仅用β系数来衡量系统风险,在各种异象的冲击下越发丧失对股票收益的解释力度

1.1.3 Fama三因子出现

研究学者们开始思考,用单个系统因子来解释股票收益率或许并不是合理的。风险有可能受多维因子影响。如:

Basu(1977)的研究表明,盈余价格比因子对股票收益率有显著的影响。他认为低市盈率的股票收益率明显高于高市盈率的股票。即市盈率对股票横截面收益的解释力可以吸收规模和市场β的解释能力。

Vipul(1998)检测公司基本面的因子对股票收益率的影响,如公司规模因子对公司的系统风险有相当大的影响。

Fama和French在1992年用美国股票市场从1929年至1963年的数据作为样本,研究了上市公司市值(ME)和账面市值比(BE/ME)对股票价格变动及其收益率的解释能力。这种现象是资本资产定价模型描述以外的。

1.2 Fama三因子的介绍

Fama和French(1993)首次提出三因子模型,把股票的账面市值比率以及规模因子作为除β以外对股票收益的解释因子。

1.2.1 核心观点

1)在原始资本资产定价模型的基础上增加市值规模因子和账面市值比因子比作为市场风险因素的补充,能够更完整的描述单个股票所包含的投资风险。
2)公司规模和账面市值比这两个因子能够很好的捕捉股票平均收益率,并且杠杆效应(leverage)和收入价格比效应(earning-price ratio E/P)对股票横截面收益的解释能力被规模因子(size)和账面市值比因子(book to market ratio)吸收了。

1.2.2 原理及模型


ai: 截距项表示单个选定股票或者投资组合i的无条件限制的平均收益,如果a在置信区间内等于0,说明三个风险因子基本能够解释研究样本股票的平均横截面收益;
Ri :是股票或投资组合i的收益率
Rf :是无风险收益率
et : 是误差项
Ri - Rf :是某选定股票或投资组合的超额收益(投资组合的收益率,Fama论文中是使用doublesort的方法构建了25个投资组合)

MKT**(市场风险因子)** : Rm(所有组合里的股票的加权回报) – Rf(无风险收益率),是整个市场组合的超额收益

SMB和HML构成步骤
1)规模组合的构建,按照股票的市价把样本分为大规模公司(big firm),中规模公司(medium firm)和小规模公司(small firm)。然后将公司的账面市值比按由高到低的顺序将股票分为高(High)、中(Medium)、低(Low)三个组合;
2)然后将公司规模和账面市值比组合成6个投资组合:小公司小账面市值比(S/L)、小公司中账面市值比(S/M)、小公司高账面市值比(S/H),大公司小账面市值比(B/L),大公司中账面市值比(B/M)、大公司高账面市值比(B/H)。
3)SMB(规模因子)和HML(账面市值比因子)公式:

SMB因子涉及到规模因子的风险,同时排除账面市值比因子的影响;同理,HML因子只涉及到账面市值比因子风险。

1.3 Fama三因子的计算

参考学习: Fama-French三因子回归A股实证(附源码)

数据来源(学习的文章):
1)HML、SMB、因变量:使用2009年-2019年全A股月度数据进行计算(用其他频率也可)
2)MKT:MKT的计算比较简单,直接使用中国资产管理研究中心提供的数据了,当然如果想自己算的话,RM可以考虑用中证全指的收益率,RF可以用10年期国债到期收益率。
总的来说,数据包括:以月份为频率的股票的股价(price)、股票的市值(mkt)、股票的市净率(pb)、MKT因子

计算部分开始
(1)数据处理

"""首先把账面市值比BM和市值mkt数据拼在一起,然后剔除新股和ST股"""
price = pd.read_csv('复权价格.csv')  # 每股股价
ST = pd.read_csv('ST.csv') # st数据
pb = pd.read_csv('PB.csv')  # 市净率(市价账面比)数据
mkt = pd.read_csv('mkt.csv')  # 股票总市值数据
ipodate = pd.read_csv('上市日期.csv') # 上市日期
# 日期处理
price['tradedate'] = pd.to_datetime(price.tradedate)
ST['entry_dt'] = pd.to_datetime(ST.entry_dt)
ST['remove_dt'] = pd.to_datetime(ST.remove_dt)
mkt['tradedate'] = pd.to_datetime(mkt.tradedate)
pb['tradedate'] = pd.to_datetime(pb.tradedate)
ipodate['ipodate'] = pd.to_datetime(ipodate.ipodate)
BM = pb.copy()
BM['BM'] = 1/BM.pb  # 先将市值账面比倒数为账面市值比
BM = BM.drop(['pb'],axis = 1)  # 丢掉市值账面比变量
f = pd.merge(BM,mkt,left_on = ['tradedate','stockcode'],right_on = ['tradedate','stockcode'])  # 将账面市值比数据和市值数据依据股票代码和日期进行合并
# 踢PB为负的
f = f.loc[f.BM > 0].reset_index(drop = True) # 选择BM>0的,然后把小于0的剔除,重新排序索引
# 踢新股:上市不满一年
ipodate['entry_date'] = ipodate.ipodate + datetime.timedelta(365)  # ipo日期 + 365天 确定一年后的日期
f = pd.merge(f,ipodate,left_on = ['stockcode'],right_on = ['stockcode']) # 合并ipo和f数据
f = f.loc[f.tradedate >= f.entry_date].reset_index(drop = True) # 选择上市满一年的,然后把不满的剔除,重新排序索引
f = f.drop(['ipodate','entry_date'],axis = 1)  # f现在有的变量:代码、tradedata、BM、mkt
# 剔ST
res =[]for dates in f.tradedate.unique(): # dates = f.tradedate.unique()[10] 交易日期去重fuse = f.loc[f.tradedate == dates]     st_use = ST.loc[ST.entry_dt <= dates] # 交易日期前进入stst_use = st_use.loc[(st_use.remove_dt > dates) | pd.isnull(st_use.remove_dt)]  # 交易日期内还在st或者移除st日期未写的定义为stscode_notst = set(fuse.stockcode).difference(set(st_use.stockcode))  fuse = fuse.set_index(['stockcode']).loc[scode_notst].reset_index() res.append(fuse)res = pd.concat(res,axis = 0) # 拼接
f = res.reset_index(drop = True)

(2)生成6个投资组合

"""
接下来生成6个投资组合:
(1)获取所有年份5月末的数据作为分组依据
(2)按市值分为两组,
(3)按账面市值比生成三组。
以上过程通过函数split_SIZE和split_BM实现,
通过apply和groupby得到每一期的分组。
"""
f['ym'] = f.tradedate.apply(lambda x:x.year*100 + x.month)  # 设置年月变量ym
f_5 = f.loc[f.ym %10 ==5].copy()  # 取所有年份5月末的数据
"""账面市值比分组:H、M、L"""
def split_BM(x):x.loc[x['BM'] >= x.BM.quantile(0.7),'group_BM'] = 'H'  # 建立group_BM组,大于等于BMt0.7数,定义为Hx.loc[x['BM'] < x.BM.quantile(0.3),'group_BM'] = 'L'return xf_5['group_BM'] = 'M'
f_5 = f_5.groupby(['ym']).apply(split_BM) #  匹配得到,划分为H、L、M
f_5 = f_5.reset_index(drop = True)
"""市值分组:B、S"""
def split_SIZE(x):x.loc[x['mkt'] >= x.mkt.median(),'group_SIZE'] = 'B'  # 建立group_SIZE组,大于等于mkt中位数,定义为Breturn xf_5['group_SIZE'] = 'S'
f_5 = f_5.groupby(['ym']).apply(split_SIZE)
f_5 = f_5.rename(columns = {'ym':'portfolio_dates'})  # 投资组合日期 yyyy05
f_5 = f_5[['stockcode','portfolio_dates','group_BM','group_SIZE']]  # f_5有如下变量
f['portfolio_dates'] = f.tradedate.apply(lambda x:x.year*100 + 5 if x.month > 5 else  (x.year - 1)*100 + 5)  # 小于5月为上年的5月末表现和大于5月为本年的5月末表现f = pd.merge(f,f_5,left_on =['stockcode','portfolio_dates'],right_on =['stockcode','portfolio_dates']) # f和f_5数据合并,得到H、L、M和B、S
f = f.reset_index(drop = True)f['portfolio_name'] = f.group_SIZE + '/' + f.group_BM  # 生成portfolio_name变量


(3)计算这六个组合的市值加权收益率(Value-weighted return)

# 先计算每个股票的股价增长率(股票收益率)
"""df.pivo用法:https://www.cnblogs.com/sunbigdata/p/8134441.html"""
"""df.stack用法:https://www.cnblogs.com/bambipai/p/7658311.html"""
ret = price.pivot(index = 'tradedate',columns = 'stockcode',values = 'price').pct_change(1).shift(-1).fillna(0)  # 计算股价增长率,缺失值补位为0
ret = ret.stack().reset_index()  # 转置成面板数据
ret = ret.rename(columns = {ret.columns[2]:'ret'})
sdate = datetime.date(2009,5,1)
f = f.loc[f.tradedate >= sdate].reset_index(drop = True) # 限制样本为2009年5月1号后
f = pd.merge(f,ret,left_on =['stockcode','tradedate'],right_on =['stockcode','tradedate'])
f.loc[f.tradedate == datetime.date(2009,5,27),'ret'] = 0 # 为什么 2009年5月27号,ret =0 ?
port_ret = f.groupby(['tradedate','portfolio_name']).apply(lambda x:(x.ret*x.mkt).sum()/x.mkt.sum()) # 计算每年每月的6个投资组合市值加权收益率
port_ret = port_ret.reset_index()
port_ret = port_ret.rename(columns = {port_ret.columns[-1]:'ret'}) # 定义每年每月的6个投资组合市值加权收益率 这个变量
# 计算这六个组合的市值加权收益率(Value-weighted return)
port_ret = f.groupby(['tradedate','portfolio_name']).apply(lambda x:(x.ret*x.mkt).sum()/x.mkt.sum()) # 计算每年每月的6个投资组合市值加权收益率
port_ret = port_ret.reset_index()
port_ret = port_ret.rename(columns = {port_ret.columns[-1]:'ret'}) # 定义每年每月的6个投资组合市值加权收益率为 这个变量ret
port_ret_pivo = port_ret.pivot(index = 'tradedate',columns = 'portfolio_name',values = 'ret')  # 由面板转为非面板 --> 转置成 6个投资组合市值加权增长率为值为变量的数据

(4)计算SMB、HML因子

# SMB因子:SMB也是每年每个月都不同的,这里是以tradedate为排序,6种组合为列变量的数据排布
# SMB = 1/3(SL + SM + SH) - 1/3(BL + BM + BH)
SMB = (port_ret_pivot['S/L'] + port_ret_pivot['S/M'] + port_ret_pivot['S/H'])/3 - (port_ret_pivot['B/L'] + port_ret_pivot['B/M'] + port_ret_pivot['B/H'])/3
# HML因子:HML也是每年每个月都不同的,这里是以tradedate为排序,6种组合为列变量的数据排布
# HML因子 HML = (SH + BH)/2 - (SL + BL)/2
HML = (port_ret_pivot['S/H'] + port_ret_pivot['B/H'])/2 - (port_ret_pivot['S/L'] + port_ret_pivot['B/L'])/2
ff3 = pd.concat([SMB,HML],axis = 1)
ff3 = ff3.reset_index()  # 把tradedate不再设置为索引
ff3.columns = ['tradedate','SMB','HML']
ff3['ym'] = ff3.tradedate.apply(lambda x:x.year*100 + x.month)  # ff3数据已经计算出各投资组合的SMB、HML

(5)计算MKT因子

"""计算MKT因子"""
# RM:全市场流通市值加权指数收益率
# RF:无风险利率
# 这里直接用中国资产管理研究中心的数据
d = pd.read_csv('fivefactor_monthly.csv')
RM_RF = d[['trdmn','mkt_rf','rf']].copy()  # mkt_rf是全市场流通市值加权指数收益率减去无风险利率
RM_RF = RM_RF.rename(columns = {'trdmn':'ym'})
ff3 = pd.merge(ff3,RM_RF,left_on = ['ym'],right_on = ['ym'])  # 合并ff3

(6) 构造因变量

"""接下来构造因变量25个投资组合"""
# 这一次对市值和账面市值比都分别分成5等分,组合之后得到25个投资组合,并计算这25个投资组合的市值加权收益率,作为因变量。
groups = 5
f_5 = f.loc[f.ym %10 ==5,['stockcode','tradedate','ym','BM','mkt']].copy() # 还是以5月末为准
f_5['g_BM'] = f_5.BM.groupby(f_5.tradedate).apply(lambda x:np.ceil(x.rank()/(len(x)/groups))) # 按照账面市值比5等分
f_5['g_SIZE'] = f_5.mkt.groupby(f_5.tradedate).apply(lambda x:np.ceil(x.rank()/(len(x)/groups))) # 按照市值5等分
f_5 = f_5.rename(columns = {'ym':'portfolio_dates'})
f_5 = f_5[['stockcode','portfolio_dates','g_BM','g_SIZE']]
f['portfolio_dates'] = f.tradedate.apply(lambda x:x.year*100 + 5 if x.month > 5 else  (x.year - 1)*100 + 5) # 同上,小于5月,划为上年
f = pd.merge(f,f_5,left_on =['stockcode','portfolio_dates'],right_on =['stockcode','portfolio_dates'])
f = f.reset_index(drop = True)
f['portfolio_name'] = f.g_BM + '/' + f.g_SIZE  # 生成portfolio_name变量
"""计算25个组合市值加权收益率的过程同6个组合收益率过程一样"""
f = pd.merge(f,ret,left_on =['stockcode','tradedate'],right_on =['stockcode','tradedate'])
f.loc[f.tradedate == datetime.date(2009,5,27),'ret'] = 0 # 为什么 2009年5月27号,ret =0 ?
port_ret_25 = f.groupby(['tradedate','portfolio_name']).apply(lambda x:(x.ret*x.mkt).sum()/x.mkt.sum()) # 计算每年每月的25个投资组合市值加权收益率
port_ret_25 = port_ret.reset_index()
port_ret_25 = port_ret.rename(columns = {port_ret.columns[-1]:'ret_25'}) # 定义每年每月的25个投资组合市值加权收益率 这个变量
f25 = port_ret.pivot(index = 'tradedate',columns = 'portfolio_name',values = 'ret_25')  # 由面板转为非面板 --> 转置成 25个投资组合市值加权收益率为值的变量的数据
f25 = f25.reset_index()  # 把tradedate不再设置为索引

(7)解释变量数据和被解释变量数据合并

# 解释变量数据和被解释变量数据合并
f25 = pd.merge(f25,ff3,left_on = ['tradedate'],right_on = ['tradedate'])
# 最后得到的数据是每年每个月的25个投资组合的市值加权收益率、6个投资组合的HML、SML、MKT
f25['Intercept'] = 1
x = f25.loc[:,['SMB','HML','mkt_rf','Intercept']].values  # 解释变量

(8)回归

# 设置回归结果的容器
r2 = []
betas = []
t = []
p = []
# 25个投资组合依次回归
for i in range(25):# i = 0y = f25.loc[:,f25.columns[i+1]].valuesmod = sm.OLS(y,x).fit()r2.append([f25.columns[i+1],mod.rsquared])betas.append([f25.columns[i+1]] + list(mod.params))t.append([f25.columns[i+1]] + list(mod.tvalues))p.append([f25.columns[i+1]] + list(mod.pvalues))
p = pd.DataFrame(p,columns = ['group','SMB','HML','mkt_rf','Intercept'])
t = pd.DataFrame(t,columns = ['group','SMB','HML','mkt_rf','Intercept'])
betas = pd.DataFrame(betas,columns = ['group','SMB','HML','mkt_rf','Intercept'])
r2 = pd.DataFrame(r2,columns = ['group','r2'])

2 Carhat 四因子模型的介绍和计算

2.1 Carhat四因子模型的介绍

2.1.1 Carhat四因子的引出

伴随着在市场中的使用,Fama-French 三因子模型也被发现存在解释能力不足的问题,其并不能解释市场中动量效应存在的问题。而Carhart 四因子模型是基于 Fama-French 三因子模型而提出的。

Jegadeesh 和 Titman(1993)提出了关于股票的动量效应,即过去收益率高的股票在未来的收益率仍然要高于过去收益率较低的股票。基于此,也就有了动量交易策略,其是利用股票的动量效应突破现有趋势的一种策略。进行动量交易时,通常假设上涨的股票会持续上涨,下跌的股票会持续下跌,然后根据这个假设来执行买入和卖出。

Carhart 四因子模型是基于 Fama-French 三因子模型而提出的

2.1.2 Carhat四因子的模型

Carhart 四因子模型是基于 Fama-French 三因子模型而提出的,,模型如下:

因此其前三个因子,即市场因子(MKT)、规模因子(SMB)及账面市值比因子(HML)是相同的,有所不同的是加入了动量因子(UMD)。

根据 Carhart 所使用的动量因子(UMD)测量方法为排序期一年,并按累计收益表现将股票同样均分为三组,前三分之一为高收益率公司(U),后三分之一为低收益率公司(D),将动量因子的期望收益设置为E(

Fama三因子和Carhat 四因子的介绍和计算相关推荐

  1. R语言选模型/用AIC BIC adjustRsq 十折交叉验证 LOOCV等验证/择参 以fama三因子模型和CAMP模型为例@[理科班的习习同学

    R语言选模型/用AIC BIC adjustRsq 十折交叉验证 LOOCV等验证/择参 以fama三因子模型和CAMP模型为例@理科班的习习同学 引入包与数据预处理 install.packages ...

  2. Fama-French三因子和五因子模型数据和Stata代码(2000-2020年)

    三因子和五因子模型 一.Fama-French三因子模型数据和Stata代码(2000-2020年) 1.数据来源:原始数据在分享文件中 2.时间跨度:2000-2020年 3.区域范围:全国 4.指 ...

  3. Netty之WebSocket和四种IO介绍

    Netty简介 一.什么是netty? 高性能 事件驱动 异步非堵塞 基于NIO的客户端,服务器端编程框架 稳定性和伸缩性 二.Netty的使用场景 高性能领域   多线程并发领域   异步通信领域 ...

  4. css样式引入形式php,引入css样式表的四种方式介绍

    一.使用STYLE属性: 将STYLE属性直接加在个别的元件标签里. 这种用法的优点 是可灵巧应用样式於各标签中,但是缺点则是没有整篇文件的『统一性』. 二.使用STYLE标签: 将样式规则写在标签之 ...

  5. mysql 模糊查询用法_mysql进阶(六)模糊查询的四种用法介绍

    mysql中模糊查询的四种用法介绍 这篇文章主要介绍了mysql中模糊查询的四种用法,需要的朋友可以参考下. 下面介绍mysql中模糊查询的四种用法: 1 %: 表示任意0个或多个字符.可匹配任意类型 ...

  6. python可以实现哪些功能_Python中实现机器学习功能的四种方法介绍

    本篇文章给大家带来的内容是关于Python中实现机器学习功能的四种方法介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 在本文中,我们将介绍从数据集中选择要素的不同方法; 并使用S ...

  7. 四象限运行模式_双向可控硅四象限触发方式介 - 双向可控硅四象限触发方式介绍_双向可控硅触发电路的设计...

    双向可控硅四象限触发方式介绍 双向可控硅是在普通可控硅的基础上发展而成的,它不仅能代替两只反极性并联的可控硅,而且仅需一个触发电路,是目前比较理想的交流开关器件.其英文名称TRIAC即三端双向交流开关 ...

  8. 四:MySQL 表介绍

    四:MySQL 表介绍 概述介绍 索引组织表 InnoDB 逻辑存储结构 表空间 段 区 页 行 InnoDB行记录格式 Compact行记录格式 行溢出数据 InnoDB数据页结构 约束 数据完整性 ...

  9. 贵州茅台的中国版四因子归因【课程作业】

    tushare ID:470138 1.导入包 import pandas as pd import numpy as np import datetime from datetime import ...

最新文章

  1. 第一次作业+105032014116
  2. Kong APIGW — OpenResty
  3. 成立快两年,阿里巴巴达摩院都干什么了?
  4. 数据结构--百度百科
  5. python argpare 模块的简单用法
  6. 青蛙学Linux—高性能负载均衡集群软件LVS
  7. python爬虫:使用BeautifulSoup进行查找
  8. Java 头像剪切及上传服务器JSP 笔记
  9. 74.iptables规则备份和恢复,firewalld
  10. Android View框架总结(一)
  11. 《Java项目开发案例整合》
  12. Idea使用SVN下载运行项目
  13. 由于您的系统没有安装html help,win10遇到“您未安装FLASH控件”的提示怎么办
  14. Vue项目url中的BASE_URL解析
  15. Chrome 翻译插件规避代码块
  16. 纽约州立石溪分校计算机科学排名,美国纽约州立大学石溪分校排名~值得一看~...
  17. javax.mail实现收发邮件
  18. mysql事务回滚是什么意思_Mysql事务提交及事务回滚是什么意思
  19. echarts 路径图
  20. 深入理解iputils网络工具-第5篇 arping:地址解析程序

热门文章

  1. C#调用百度翻译API
  2. [Android] 代码获取手机系统类型(小米MIUI、华为EMUI、魅族FLYME)
  3. 针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引。
  4. 政府大数据的资源库建设
  5. MyBatis中大于号以及小于号的表达方式
  6. java:去除数组重复元素的四种方法
  7. 《十周成为数据分析师》笔记——业务线 第五节 用户画像体系
  8. volatile限定符
  9. 力扣772 基本计算器 III
  10. Python爬虫--喜马拉雅音频爬取