Enseñarte paso a paso cómo implementar el modelo de tres factores de Fama

Acerca del modelo de tres factores de Fama

El modelo de tres factores de Fama-French es una extensión del modelo de valoración de activos de capital (CAPM) que se utiliza para explicar la variabilidad de los rendimientos de las acciones. Este modelo fue propuesto por Eugene Fama y Kenneth French en 1992.

Este modelo considera el impacto de tres factores en el rendimiento de las acciones: factor de riesgo de mercado, factor de capitalización de mercado y factor de valor. Los factores de riesgo de mercado se refieren al riesgo general del mercado de valores, que puede estar representado por índices de mercado. El factor de capitalización de mercado se refiere a la capitalización de mercado de una empresa, que puede representarse mediante el índice de capitalización de mercado. El factor de valor se refiere al nivel de valoración de la empresa, que puede representarse mediante la relación libro-mercado (B/M). Estos tres factores se consideran factores importantes en la rentabilidad de las acciones.

El modelo de tres factores de Fama cree que el rendimiento esperado de una acción se puede calcular mediante la siguiente fórmula:

E(Ri) = Rf + βi(Prima de riesgo de mercado) + si(SMB) + hi(HML)

Entre ellos, E (Ri) representa el rendimiento esperado de la acción i, Rf representa la tasa de rendimiento libre de riesgo, βi representa el coeficiente de riesgo de mercado de la acción i, la prima de riesgo de mercado representa la tasa de rendimiento del factor de riesgo de mercado menos el riesgo. -tasa de rendimiento libre, y si representa la acción i El coeficiente del factor de capitalización de mercado de , SMB representa el exceso de rendimiento del factor de capitalización de mercado, hi representa el coeficiente del factor de valor de la acción i y HML representa el exceso de rendimiento del factor de valor .

Al considerar la capitalización de mercado y los factores de valor, el modelo de tres factores de Fama puede explicar mejor la variabilidad de los rendimientos de las acciones. El modelo se utiliza ampliamente en áreas como la gestión de carteras, la gestión de riesgos y la fijación de precios de activos.

Implementación de código Python

Dado que el modelo anterior requiere el uso de datos como el valor de mercado de las acciones y la relación libro-mercado, primero debemos obtener estos datos. A continuación se muestra una forma de obtener datos sobre la capitalización del mercado de valores de China y la relación libro-mercado:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

dieciséis

17

import pandas as pd

import tushare as ts

# 获取股票列表

stock_list = ts.get_stock_basics().index.tolist()

# 获取股票市值数据

market_cap = ts.get_stock_basics().loc[:, 'totalAssets']

# 获取股票账面市值比数据

book_to_market = ts.get_stock_basics().loc[:, 'bvps'/ ts.get_stock_basics().loc[:, 'pb']

# 将市值和账面市值比数据合并到一个DataFrame中

data = pd.concat([market_cap, book_to_market], axis=1)

data.columns = ['market_cap''book_to_market']

data.index.name = 'code'

data = data.dropna()

A continuación, podemos utilizar los datos del valor de mercado y la relación libro-mercado obtenidos anteriormente, así como los datos de rendimiento de las acciones, para implementar el cálculo del modelo de tres factores de Fama. Aquí hay una implementación simple:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

dieciséis

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

import numpy as np

import statsmodels.api as sm

# 获取股票收益率数据

start_date = '2020-01-01'

end_date = '2020-12-31'

return_data = pd.DataFrame()

for code in stock_list:

    try:

        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq',

                                   factors=['tor']).set_index('trade_date')['pct_chg']

        return_data[code] = stock_return

    except:

        pass

# 计算市场指数收益率

market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date,

                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']

market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中

data = pd.concat([return_data, market_return], axis=1)

data = data.dropna()

# 计算超额收益率

data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中

data = pd.concat([data, market_cap, book_to_market], axis=1)

data.columns = stock_list + ['market_return''market_cap''book_to_market']

# 计算因子收益率

factor_data = pd.DataFrame()

factor_data['market_factor'= market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date,

                                                          end_date=end_date, adj='qfq',

                                                          factors=['tor']).set_index('trade_date')['pct_chg']

factor_data['size_factor'= sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid

factor_data['value_factor'= sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算法玛三因子模型的参数

= sm.add_constant(factor_data)

model = sm.OLS(np.array(data.mean()), X)

results = model.fit()

print(results.summary())

  

以上代码中,我们使用了tushare库获取股票数据,并使用statsmodels库进行回归分析。具体来说,我们首先获取了股票收益率、市场指数收益率、股票市值和账面市值比等数据,然后计算了超额收益率,并将这些数据合并到一个DataFrame中。接着,我们计算了市场因子、规模因子和价值因子的收益率,并利用OLS回归分析计算了法玛三因子模型的参数。

需要注意的是,以上代码只是一个简单的示例,实际应用中还需要考虑很多其他因素,如数据处理、缺失值处理、数据标准化等。此外,法玛三因子模型也有其局限性,如不能很好地解释一些股票市场现象等。因此,在实际应用中需要根据具体情况进行调整和改进。

因子有效性检验

当使用法玛三因子模型时,我们需要确认市场因子、规模因子和价值因子是否有效。以下是几种在Python中进行因子有效性检验的方法:

1 因子收益率的t检验

首先,我们可以使用t检验来检验市场因子、规模因子和价值因子的收益率是否显著不为零。我们可以通过计算每个因子收益率的t统计量,并检验其显著性水平,来判断该因子是否有效。以下是一个简单的示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

import pandas as pd

import numpy as np

import statsmodels.api as sm

# 获取股票收益率数据

start_date = '2020-01-01'

end_date = '2020-12-31'

return_data = pd.DataFrame()

for code in stock_list:

    try:

        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq',

                                   factors=['tor']).set_index('trade_date')['pct_chg']

        return_data[code] = stock_return

    except:

        pass

# 计算市场指数收益率

market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date,

                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']

market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中

data = pd.concat([return_data, market_return], axis=1)

data = data.dropna()

# 计算超额收益率

data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中

data = pd.concat([data, market_cap, book_to_market], axis=1)

data.columns = stock_list + ['market_return''market_cap''book_to_market']

# 计算因子收益率

factor_data = pd.DataFrame()

factor_data['market_factor'= market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date,

                                                          end_date=end_date, adj='qfq',

                                                          factors=['tor']).set_index('trade_date')['pct_chg']

factor_data['size_factor'= sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid

factor_data['value_factor'= sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算t检验的p值

ttest = sm.stats.ttest_ind(factor_data, np.zeros(factor_data.shape), axis=0)

# 打印检验结果

print(ttest)

  

以上代码中,我们首先计算了每个因子的收益率,然后使用OLS回归分析计算了每个因子的残差,即每个因子收益率中的alpha值。接着,我们计算了每个因子收益率的t统计量和p值,并输出检验结果。

2 因子回归的 $R^2$ 值

除了t检验之外,我们还可以使用因子回归的 $R^2$ 值来评估市场因子、规模因子和价值因子的有效性。$R^2$ 值表示模型中因子收益率对总收益率的解释程度,值越高则说明因子对总收益率的解释程度越大。以下是一个简单的示例:

复制代码

import pandas as pd
import numpy as np
import statsmodels.api as sm

# 获取股票收益率数据
start_date = '2020-01-01'
end_date = '2020-12-31'
return_data = pd.DataFrame()
for code in stock_list:
    try:
        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq', 
                                   factors=['tor']).set_index('trade_date')['pct_chg']
        return_data[code] = stock_return
    except:
        pass

# 计算市场指数收益率
market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date, 
                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']
market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中
data = pd.concat([return_data, market_return], axis=1)
data = data.dropna()

# 计算超额收益率
data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中
data = pd.concat([data, market_cap, book_to_market], axis=1)
data.columns = stock_list + ['market_return', 'market_cap', 'book_to_market']

# 计算因子收益率
factor_data = pd.DataFrame()
factor_data['market_factor'] = market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date, 
                                                          end_date=end_date, adj='qfq', 
                                                          factors=['tor']).set_index('trade_date')['pct_chg']
factor_data['size_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid
factor_data['value_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算因子回归的R2值
y = data.mean()
X = sm.add_constant(factor_data)
model = sm.OLS(y, X).fit()
rsquared = model.rsquared

# 打印检验结果
print(rsquared)

复制代码

以上代码中,我们首先计算了每个因子的收益率,然后使用OLS回归分析计算了每个因子的残差,即每个因子收益率中的alpha值。接着,我们将股票超额收益率和因子收益率合并到一个DataFrame中,然后计算因子回归的 $R^2$ 值。最后,我们输出了检验结果。

3 因子相关性分析

除了单独检验每个因子的有效性之外,我们还可以使用因子相关性分析来评估每个因子对投资组合表现的贡献程度。这里我们使用热图来显示每个因子之间的相关性。以下是一个简单的示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

import pandas as pd

import seaborn as sns

import matplotlib.pyplot as plt

# 获取股票收益率数据

start_date = '2020-01-01'

end_date = '2020-12-31'

return_data = pd.DataFrame()

for code in stock_list:

    try:

        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq',

                                   factors=['tor']).set_index('trade_date')['pct_chg']

        return_data[code] = stock_return

    except:

        pass

# 计算市场指数收益率

market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date,

                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']

market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中

data = pd.concat([return_data, market_return], axis=1)

data = data.dropna()

# 计算超额收益率

data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中

data = pd.concat([data, market_cap, book_to_market], axis=1)

data.columns = stock_list + ['market_return''market_cap''book_to_market']

# 计算因子收益率

factor_data = pd.DataFrame()

factor_data['market_factor'= market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date,

                                                          end_date=end_date, adj='qfq',

                                                          factors=['tor']).set_index('trade_date')['pct_chg']

factor_data['size_factor'= sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid

factor_data['value_factor'= sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算因子相关性

corr_matrix = factor_data.corr()

# 绘制热图

sns.heatmap(corr_matrix, annot=True, cmap='RdYlBu')

plt.show()

  

以上代码中,我们首先计算了每个因子的收益率和超额收益率,然后将这些数据合并到一个DataFrame中。接着,我们使用OLS回归分析计算了每个因子的残差,即每个因子收益率中的alpha值。然后,我们计算了每个因子之间的相关性,并使用热图可视化了结果。

法玛三因子模型的优缺点

法玛三因子模型的优点:

  1. 解释力强:相较于CAPM模型,法玛三因子模型的解释力更强,能够更好地解释股票收益率的变化。

  2. 考虑了多个因素:相较于单因子模型,法玛三因子模型考虑了市场因子、规模因子和价值因子,更全面地考虑了股票收益率的影响因素。

  3. 可解释性强:法玛三因子模型中的三个因子,即市场因子、规模因子和价值因子,都是经济学上有实际意义的因素,因此其结果更容易被解释。

法玛三因子模型的缺点:

  1. 忽略了其他因素:法玛三因子模型只考虑了市场因子、规模因子和价值因子,忽略了其他可能对股票收益率有影响的因素,如流动性、动量等。

  2. 样本限制:法玛三因子模型的样本通常是历史股票数据,而历史表现并不能保证未来表现,因此其预测能力有限。

  3. 可能存在共线性问题:法玛三因子模型中的因子可能存在共线性问题,导致其解释能力下降。

  4. 不适用于所有市场:法玛三因子模型的适用范围有限,可能无法适用于所有市场。例如,一些新兴市场可能存在不同的因子影响股票收益率,无法使用法玛三因子模型来解释其表现。

综上所述,法玛三因子模型虽然具有一定的局限性,但在投资组合管理和股票选择方面仍然具有一定的实用性和可靠性。

如何改进提升

虽然法玛三因子模型具有较好的解释股票收益率的能力,但是其仍然存在一些缺点和局限性。下面是一些改进和提升三因子模型的方法:

1 添加其他因子:法玛三因子模型只考虑了市场因子、规模因子和价值因子,可以添加其他因子,如动量、流动性等,来提升模型的解释能力。可以使用pyfolio库中的get_factor_returns函数获取更多的因子数据,例如动量因子和波动率因子:

1

2

3

4

5

6

7

8

import pyfolio as pf

start_date = '2015-01-01'

end_date = '2021-12-31'

tickers = ['AAPL''MSFT''AMZN''GOOG''FB']

factor_names = ['market_beta''size_factor''value_factor''momentum_factor''volatility_factor']

factor_data = pf.utils.get_factor_returns(factor_names, start_date=start_date, end_date=end_date)

2 考虑时间变化:股票市场中因子的影响可能会随着时间变化而变化,可以建立时间变化的因子模型,或者采用滚动回归来考虑时间变化对因子的影响。 可以使用rolling函数进行滚动回归,并将时间窗口设置为1年或更长时间:

1

2

3

4

5

6

7

8

9

import pandas as pd

import statsmodels.api as sm

rolling_window = 252

factor_data_rolling = pd.DataFrame(index=factor_data.index)

for factor_name in factor_names:

    factor_data_rolling[factor_name] = factor_data[factor_name].rolling(window=rolling_window).apply(lambda x: sm.OLS(x, sm.add_constant(factor_data[['market_beta''size_factor''value_factor']]).loc[x.index]).fit().params)

factor_data_rolling = factor_data_rolling.dropna()

3 考虑非线性关系:股票收益率和因子之间可能存在非线性关系,可以使用非线性回归模型来建立因子模型,或者使用机器学习方法来建立预测模型。 可以使用scikit-learn库中的多项式回归模型来建立非线性关系的因子模型:

1

2

3

4

5

6

7

from sklearn.linear_model import LinearRegression

from sklearn.preprocessing import PolynomialFeatures

poly_degree = 2

poly_features = PolynomialFeatures(poly_degree, include_bias=False)

X_poly = poly_features.fit_transform(factor_data[['market_beta''size_factor''value_factor']])

model = LinearRegression().fit(X_poly, factor_data['returns'])

  或者使用scikit-learn库中的机器学习模型来建立因子模型,例如随机森林模型:

1

2

3

4

from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=100, random_state=0)

model.fit(factor_data[['market_beta''size_factor''value_factor']], factor_data['returns'])

4 解决共线性问题:法玛三因子模型中的因子可能存在共线性问题,可以使用主成分分析等方法来减少因子之间的共线性,提高模型的解释能力。 可以使用scikit-learn库中的主成分分析模型来减少因子之间的共线性:

1

2

3

4

5

from sklearn.decomposition import PCA

n_components = 3

pca = PCA(n_components=n_components)

X_pca = pca.fit_transform(factor_data[['market_beta''size_factor''value_factor']])

5 使用更多数据:使用更多的数据来建立因子模型,可以提高模型的预测能力和稳健性。 可以使用Quandl等数据源获取更多的历史数据来建立因子模型:

1

2

3

4

5

6

7

import quandl

quandl.ApiConfig.api_key = 'your_api_key'

data = quandl.get_table('SHARADAR/SF1', ticker=tickers, dimension='MRY', qopts={ 'columns': ['ticker''date''marketcap''roe''pb']})

data = data.pivot(index='date', columns='ticker')

data.columns = [f"{col[0]}_{col[1]}" for col in data.columns]

data = data.dropna()

6 考虑国别和行业因素:股票收益率受到不同国别和行业因素的影响,可以建立考虑国别和行业因素的多因子模型,来提高模型的解释能力。 可以使用pyfolio库中的get_industry_returns函数获取行业因子数据,并使用alpha_vantage等数据源获取国别因子数据:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import alpha_vantage

from alpha_vantage.timeseries import TimeSeries

import pyfolio as pf

# 使用alpha_vantage获取国别因子数据

ts = TimeSeries(key='YOUR_API_KEY', output_format='pandas')

data, meta_data = ts.get_daily(symbol='SPY', outputsize='full')

data.columns = ['open''high''low''close''volume']

data = data[['close']]

data = data.pct_change().dropna()

data.columns = ['market_factor']

# 使用pyfolio获取行业因子数据

industry_data = pf.utils.get_industry_returns('morningstar''usa')

industry_data.columns = ['industry_factor']

# 合并国别和行业因子数据

factor_data = pd.concat([data, industry_data], axis=1).dropna()

factor_data = factor_data.resample('M').last()

# 运用法玛三因子模型进行分析

...

7 考虑投资组合构建方法:可以使用优化模型来构建投资组合,例如使用CVXPY库中的优化模型:

1

2

3

4

5

6

7

8

9

10

pythonCopy codeimport cvxpy as cp

weights = cp.Variable(3)

constraints = [cp.sum(weights) == 1, weights >= 0]

expected_return = factor_data_rolling['returns'].mean()

cov_matrix = factor_data_rolling[['market_beta''size_factor''value_factor']].cov()

risk = cp.quad_form(weights, cov_matrix)

objective = cp.Minimize(risk - 0.5 * gamma * expected_return * cp.quad_form(weights, cov_matrix))

problem = cp.Problem(objective, constraints)

problem.solve()

Supongo que te gusta

Origin blog.csdn.net/qq_41221596/article/details/133441046
Recomendado
Clasificación