เราได้พูดถึง Factor Investing ไปแล้ว 2 บทความวันนี้จะเป็นบทความที่ 3 เราจะลองใช้ sklearn ในการประยุกต์ใช้ ML ในงาน Factor Investing โดยใช้ข้อมูลตัวอย่าง Data set “200+ Financial Indicators of US stocks (2014–2018)” dataset จาก Kaggle.
เราจะเริ่มต้นด้วยแบบจำลองคลาสสิกอย่าง Fama and French (1992).
จัดอันดับบริษัทตามเกณฑ์ที่กำหนด
จาก พอร์ตการลงทุน (เช่น กลุ่มที่เป็น Factor เดียวกัน) ประกอบด้วยหุ้นจำนวนเท่ากันตามการจัดอันดับ (บทความนี้ใช้สื่อกลาง)
เราจะเริ่มด้วยปัจจัยง่ายๆ คือ Size Factor เราจะจัดกลุ่มหุ้นออกเป็นสองกลุ่มใหญ่/เล็ก เราจะดูว่าขนาดสามารถสร้างอัลฟ่าได้หรือไม่
Year_lst = ["2014", "2015", "2016", "2017", "2018"]
dic_alpha_bigcap = {}
for Year in Year_lst :
data = df_all[df_all['Year'] == Year]
filter_value = data[["Market Cap"]].median()[0]
Big_Cap = data[data['Market Cap'] > filter_value]
print("Year : ", Year )
print("Big cap alpha", Big_Cap["Alpha"].mean())
dic_alpha_bigcap [Year] = Big_Cap["Alpha"].mean()
Year_lst = ["2014", "2015", "2016", "2017", "2018"]
dic_alpha_Small_Cap = {}
for Year in Year_lst :
data = df_all[df_all['Year'] == Year]
filter_value = data[["Market Cap"]].median()[0]
Small_Cap = data[data['Market Cap'] < filter_value]
print("Year : ", Year )
print("Small cap alpha", Small_Cap["Alpha"].mean())
dic_alpha_Small_Cap [Year] = Small_Cap["Alpha"].mean()
ณ จุดนี้ เราอาจสรุปได้ว่าปี 2014-2018 บิ๊กแคป ให้ผลตอบแทนมากกว่า Small cap เราจะทำเช่นนี้กับตัวแปรทั้งหมด
def filter_data_top (column,df_all ) :
Year_lst = ["2014", "2015", "2016", "2017", "2018"]
dic_alpha = {}
for Year in Year_lst :
data = df_all[df_all['Year'] == Year]
filter_value = data[[column]].median()[0]
filterdata = data[data[column] > filter_value]
print("Year : ", Year )
print(column, filterdata["Alpha"].mean())
dic_alpha[Year] = filterdata["Alpha"].mean()
return dic_alpha
def filter_data_below (column,df_all ) :
Year_lst = ["2014", "2015", "2016", "2017", "2018"]
dic_alpha = {}
for Year in Year_lst :
data = df_all[df_all['Year'] == Year]
filter_value = data[[column]].median()[0]
filterdata = data[data[column] < filter_value]
print("Year : ", Year )
print(column, filterdata["Alpha"].mean())
dic_alpha[Year] = filterdata["Alpha"].mean()
return dic_alpha
lst_alpha_all_top = []
for factor in df_all.columns[2:] :
try:
print(factor)
dic_alpha = filter_data_top (column= factor,df_all = df_all)
df__alpha = pd.DataFrame.from_dict(dic_alpha, orient='index',columns=[factor])
lst_alpha_all_top.append(df__alpha)
except:
print("error")
เราจะได้ตารางนี้
The Big Question ปัจจัยอะไรที่สร้าง Alpha?
เมื่อวิเคราะห์ผลตอบแทนของหุ้น หากเราคิดว่าผลตอบแทนทั้งหมดของหุ้นทั้งหมดซ้อนอยู่ในเวกเตอร์ 'r' และ 'x' เป็นตัวแปรที่ล้าหลังซึ่งแสดงพลังในการทำนายในการวิเคราะห์การถดถอย อาจเป็นการดึงดูดให้สรุปว่า 'x' เป็นตัวทำนายผลตอบแทนที่ดีหากค่าสัมประสิทธิ์ 'b-hat' ที่ประมาณไว้มีนัยสำคัญทางสถิติตามเกณฑ์ที่ระบุ ในการทดสอบความสำคัญของ 'x' ในฐานะปัจจัยในการทำนายผลตอบแทน เราสามารถใช้การทดสอบความสำคัญของปัจจัย โดยที่ 'x' ถือเป็นปัจจัยหนึ่ง และ 'y' เป็นอัลฟ่า ในสมการ Fama และภาษาฝรั่งเศส โดยทั่วไปแล้ว 'y' จะแสดงเป็น 'Return' แต่ก็สามารถตีความได้ว่า 'Return ลบ Ri และ Ri-Rf' ซึ่งก็คืออัลฟาเป็นหลัก แม้ว่าเราจะไม่ลงลึกในรายละเอียดของส่วนนี้ที่นี่ แต่คุณสามารถดูบทความนี้ได้ หากคุณสนใจที่จะเรียนรู้เพิ่มเติมเกี่ยวกับหัวข้อนี้”
หมายเหตุ : เราจำเป็นต้องเปลี่ยนตัวแปรเป็นเปอร์เซ็นไทล์
Year_lst = ["2014", "2015", "2016", "2017", "2018"]
dic_rank = {}
for Year in Year_lst :
data = df_all[df_all['Year'] == Year]
df_rank = df_all.rank(pct=True)
dic_rank[Year] = df_rank
df_rank = pd.concat(dic_rank)
How to use ML to improve Factor Investing
เราได้อธิบายไปแล้วก่อนหน้านี้ว่าการลงทุนแบบปัจจัยทำงานอย่างไร สามารถใช้เทคนิคการเรียนรู้ของเครื่อง (ML) เพื่อปรับปรุงการลงทุนด้านปัจจัยได้หลายวิธี อัลกอริธึม ML สามารถช่วยระบุปัจจัยที่เกี่ยวข้องด้วยพลังการทำนาย ปรับการรวมกันของปัจจัยให้เหมาะสม กำหนดเวลาที่เหมาะสมของปัจจัยที่เปิดรับ ปรับปรุงการจัดการความเสี่ยง เพิ่มประสิทธิภาพการสร้างพอร์ตโฟลิโอ และรวมแหล่งข้อมูลทางเลือก ด้วยการวิเคราะห์ข้อมูลในอดีตและใช้อัลกอริธึม ML นักลงทุนสามารถระบุปัจจัยต่างๆ เพิ่มประสิทธิภาพชุดค่าผสม และปรับความเสี่ยงแบบไดนามิกตามสภาวะตลาด เทคนิค ML ยังสามารถปรับปรุงมาตรการจัดการความเสี่ยงและรวมข้อมูลทางเลือกเพื่อให้ได้ข้อมูลเชิงลึกที่ดีขึ้น
เราใช้การถดถอยเชิงเส้นโดยใช้คลาส LinearRegression จากโมดูล sklearn.linear_model ใน Python เป้าหมายคือเพื่อให้พอดีกับแบบจำลองการถดถอยเชิงเส้นกับข้อมูลใน df_rank DataFrame เพื่อทำนายค่าของตัวแปรตาม ซึ่งแสดงเป็น y โดยใช้ค่าของตัวแปรอิสระ ซึ่งแสดงเป็น X ซึ่งได้มาจากคอลัมน์ "อัตราส่วน PE" ของ df_rank
Import LinearRegression
from sklearn.linear_model import LinearRegression
Import LinearRegression จากโมดูล sklearn.linear_model ซึ่งจัดเตรียมการใช้งานการถดถอยเชิงเส้นใน scikit-learn ซึ่งเป็นไลบรารีการเรียนรู้ของเครื่องยอดนิยมใน Python
กำหนดตัวแปรตาม:
y = df_all["Alpha"]
บรรทัดนี้กำหนดคอลัมน์ "Alpha" ของ df_all DataFrame ให้กับตัวแปร y ซึ่งแสดงถึงตัวแปรตามในโมเดลการถดถอยเชิงเส้น
X = df_rank[["PE ratio"]].fillna(value=df_rank["PE ratio"].mean())
กำหนด DataFrame ที่มีคอลัมน์ "อัตราส่วน PE" ของ df_rank DataFrame ให้กับตัวแปร X ซึ่งแสดงถึงตัวแปรอิสระในโมเดลการถดถอยเชิงเส้น วิธีการเติม () ใช้เพื่อเติมค่าที่ขาดหายไปในคอลัมน์ "อัตราส่วน PE" ด้วยค่าเฉลี่ยของคอลัมน์
PElin_reg = LinearRegression()
สร้างอินสแตนซ์ของคลาส LinearRegression และกำหนดให้กับตัวแปร PElin_reg
พอดีกับแบบจำลองการถดถอยเชิงเส้น:
PElin_reg.fit(X, y)
เราสร้างโมเดลการถดถอยเชิงเส้นกับข้อมูล โดยใช้ค่าของ X เป็นตัวแปรอิสระ และ y เป็นตัวแปรตาม
แยกค่าสัมประสิทธิ์ของแบบจำลอง:
PElin_reg.intercept_, PElin_reg.coef_
เราจะหา intercept และค่าสัมประสิทธิ์ของแบบจำลองการถดถอยเชิงเส้น ซึ่งแสดงถึงพารามิเตอร์โดยประมาณของแบบจำลอง การสกัดกั้นเข้าถึงได้โดยใช้แอตทริบิวต์ intercept_ และเข้าถึงค่าสัมประสิทธิ์โดยใช้แอตทริบิวต์ coef_ ค่าเหล่านี้สามารถให้ข้อมูลเชิงลึกเกี่ยวกับความสัมพันธ์ระหว่างตัวแปรอิสระและตัวแปรตามในแบบจำลองการถดถอยเชิงเส้น
ทำซ้ำกับ ROE
from sklearn.linear_model import LinearRegression
y = df_all["Alpha"]
X = df_rank[["ROE"]].fillna(value=df_rank["ROE"].mean() )
ROElin_reg = LinearRegression()
ROElin_reg.fit(X, y)
ROElin_reg.intercept_, ROElin_reg.coef_
And plot
import matplotlib.pyplot as plt
X1 = df_rank[["PE ratio"]].fillna(value=df_rank["PE ratio"].mean() )
X2 = df_rank[["ROE"]].fillna(value=df_rank["ROE"].mean() )
plt.figure(figsize=(6, 4)) # extra code – not needed, just formatting
plt.plot( X1, PElin_reg.predict(X1), "r-", label="PE")
plt.plot(X2 , ROElin_reg.predict(X2) , "b-", label="ROE")
# extra code – beautifies and saves Figure 4–2
plt.xlabel("$x_1$")
plt.ylabel("$y$", rotation=0)
# plt.axis([1, 1, ])
plt.grid()
plt.legend(loc="upper left")
plt.show()
เราจะเห็นว่าเส้น PE มีความชันสูงกว่า ( coef_) ดังนั้น เราสามารถพูดได้ว่า PE สามารถทำนายค่าอัลฟ่าได้ ถ้าเรามีหุ้น 3 ตัว และเราต้องการรู้ว่าตัวไหนจะมีประสิทธิภาพ
เราจะพยายามทำนายอันดับของอัลฟ่าจาก 10 ตัวแปร
y = df_all["Alpha"]
X = df_rank.fillna(value=df_rank.mean() )
bestfeatures = SelectKBest(k=10, score_func=f_regression)
fit = bestfeatures.fit(X,y)
repeat
from sklearn.linear_model import LinearRegression
top_fest = featureScores.nlargest(10,'Score')["Specs"].tolist()
y = df_rank["Alpha"]
X = df_rank[top_fest].fillna(value=df_rank[top_fest].mean() )
lin_reg = LinearRegression()
lin_reg.fit(X, y)
lin_reg.predict(X)
Handle data
df_ = df_all[["Unnamed: 0", "Sector", "Year"]]
df_["Alpha_rank"] = df_rank["Alpha"]
df_["Predict_Alpha"] = lin_reg.predict(X)
print MSE
from sklearn.metrics import mean_squared_error
X = df_["Unnamed: 0"]
Y1 = df_["Alpha_rank"]
Y2 = df_["Predict_Alpha_rank"]
mean_squared_error(Y1, Y2)
MSE = 0.07 แสดงว่าโดยเฉลี่ยแล้ว ความแตกต่างกำลังสองระหว่างค่าที่ทำนายกับค่าจริง (เช่น the residuals) ค่อนข้างน้อย โดยทั่วไป MSE ที่ต่ำกว่าจะบ่งชี้ถึงประสิทธิภาพของแบบจำลองที่ดีกว่า เนื่องจากเป็นการบ่งชี้ว่าการคาดคะเนของแบบจำลองนั้นใกล้เคียงกับค่าจริงมากกว่า
แต่,
import matplotlib.pyplot as plt
X = df_["Unnamed: 0"].head(30)
Y1 = df_["Alpha_rank"].head(30)
Y2 = df_["Predict_Alpha"].head(30)
plt.figure(figsize=(6, 6)) # extra code – not needed, just formatting
plt.plot( X, Y1, "r.", label="Alpha")
plt.plot( X , Y2 , "b.", label="Predict_Alpha")
# extra code – beautifies and saves Figure 4–2
plt.xlabel("$x_1$")
plt.ylabel("$y$", rotation=0)
# plt.axis([1, 1, ])
plt.grid()
plt.legend(loc="upper left")
plt.show()
เราจะเห็นว่า แม้ว่า MSE จะน้อยกว่า แต่เราจะเห็นว่าค่าที่ทำนายอยู่ตรงกลาง นั่นเป็นเพราะข้อจำกัดของ Liner regression model
ความซับซ้อนในการคำนวณ
ตอนนี้เราจะดูวิธีที่แตกต่างกันมากในการฝึกโมเดลการถดถอยเชิงเส้น ซึ่งเหมาะกว่าสำหรับกรณีที่มีคุณสมบัติจำนวนมากหรืออินสแตนซ์การฝึก Overfitting
Gradient Descent
Gradient descent เป็นอัลกอริธึมการปรับให้เหมาะสมที่ใช้กันทั่วไปในการเรียนรู้ของเครื่องเพื่อลดการสูญเสียหรือ loss ฟังก์ชันในระหว่างกระบวนการฝึกโมเดล เป็นอัลกอริธึมการปรับให้เหมาะสมแบบวนซ้ำที่ปรับพารามิเตอร์แบบจำลองในทิศทางของการไล่ระดับสีเชิงลบของฟังก์ชันต้นทุน เพื่อค้นหาค่าที่เหมาะสมที่สุดสำหรับพารามิเตอร์ที่ลดฟังก์ชันต้นทุนให้เหลือน้อยที่สุด
from sklearn.linear_model import SGDRegressor
sgd_reg = SGDRegressor(max_iter=100000, tol=1e-5, penalty=None, eta0=0.01,
n_iter_no_change=100, random_state=42)
sgd_reg.fit(X, y.ravel()) # y.ravel() because fit() expects 1D targets
Learning Curves
บางครั้งเรามีตัวแปรมากเกินไป เราต้องการพอดีกับข้อมูลการฝึกอบรมที่ดีกว่าการถดถอยเชิงเส้นธรรมดา กรณีนี้เราใช้ 100 ตัวแปร เราใช้ฟังก์ชัน learning_curve เพื่อช่วยเรา
from sklearn.model_selection import learning_curve
train_sizes, train_scores, valid_scores = learning_curve(
LinearRegression(), X, y, train_sizes=np.linspace(0.01, 1.0, 40), cv=5,
scoring="neg_root_mean_squared_error")
train_errors = -train_scores.mean(axis=1)
valid_errors = -valid_scores.mean(axis=1)
plt.figure(figsize=(6, 4)) # extra code – not needed, just formatting
plt.plot(train_sizes, train_errors, "r-+", linewidth=2, label="train")
plt.plot(train_sizes, valid_errors, "b-", linewidth=3, label="valid")
# extra code – beautifies and saves Figure 4–15
plt.xlabel("Training set size")
plt.ylabel("RMSE")
plt.grid()
plt.legend(loc="upper right")
#plt.axis([0, 80, 0, 2.5])
plt.show()
ข้อมูลขนาดชุดการฝึกที่เหมาะสมที่สุดคือเส้นสีแดงใกล้กับเส้นสีน้ำเงิน หากเส้นสีแดงต่ำกว่าเส้นสีน้ำเงินมาก จะเรียกว่า Underfit ในทางกลับกัน หากเส้นสีแดงอยู่สูงกว่าเส้นสีน้ำเงิน Overfit มาก
เกิน ……………………
เท่านี้เราก็จะได้ค่าสัมประสิทธิ์ ค่าสัมประสิทธิ์สามารถบอกได้ว่าปัจจัยใดกำหนดผลตอบแทน เรายังมีรายละเอียดอีกมากที่เราข้ามไป (Normalization, Factor engineering, etc.) อัลกอริทึมอื่นๆ (Regularized Linear Models, Lasso Regression, Elastic Net) รวมถึงการใช้ ML ในขั้นตอนต่างๆ .
Ref :
Machine Learning for Factor Investing by Guillaume Coqueret
“Advances in Financial Machine Learning” by Marcos Lopez de Prado: This book provides an in-depth overview of the intersection of finance and machine learning, including techniques for factor modeling, risk management, and portfolio optimization using machine learning algorithms.
“Machine Learning for Factor Investing: Empirical Methods for Systematic Trading” by Marcos Lopez de Prado:
“Applied Machine Learning” by Kelleher, Mac Namee, and D’Arcy
“Quantitative Momentum: A Practitioner’s Guide to Building a Momentum-Based Stock Selection System” by Wesley R. Gray and Jack R. Vogel
Hands-on ml with scikit-learn keras and tensorflow by Geron Aurelien
Machine Learning and Data Science Blueprints for Finance: From Building Trading Strategies to Robo-Advisors Using Python by Hariom Tatsat , Sahil Puri , Brad Lookabaugh
コメント