top of page

พัฒนา Your Factor Investing ด้วย Machine Learning โดย sklearn

เราได้พูดถึง Factor Investing ไปแล้ว 2 บทความวันนี้จะเป็นบทความที่ 3 เราจะลองใช้ sklearn ในการประยุกต์ใช้ ML ในงาน Factor Investing โดยใช้ข้อมูลตัวอย่าง Data set “200+ Financial Indicators of US stocks (2014–2018)” dataset จาก Kaggle.


เราจะเริ่มต้นด้วยแบบจำลองคลาสสิกอย่าง Fama and French (1992).

  1. จัดอันดับบริษัทตามเกณฑ์ที่กำหนด

  2. จาก พอร์ตการลงทุน (เช่น กลุ่มที่เป็น Factor เดียวกัน) ประกอบด้วยหุ้นจำนวนเท่ากันตามการจัดอันดับ (บทความนี้ใช้สื่อกลาง)

  3. เราจะเริ่มด้วยปัจจัยง่ายๆ คือ 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 :

  1. “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.

  2. “Machine Learning for Factor Investing: Empirical Methods for Systematic Trading” by Marcos Lopez de Prado:

  3. “Applied Machine Learning” by Kelleher, Mac Namee, and D’Arcy

  4. “Quantitative Momentum: A Practitioner’s Guide to Building a Momentum-Based Stock Selection System” by Wesley R. Gray and Jack R. Vogel

  5. Hands-on ml with scikit-learn keras and tensorflow by Geron Aurelien

  6. Machine Learning and Data Science Blueprints for Finance: From Building Trading Strategies to Robo-Advisors Using Python by Hariom Tatsat , Sahil Puri , Brad Lookabaugh


ดู 122 ครั้ง0 ความคิดเห็น

โพสต์ล่าสุด

ดูทั้งหมด

Hidden Markov Models

コメント


bottom of page