“การลงทุนที่ดีที่การลงทุนที่กำไรมากที่สุด” นั่นมันสำหรับมือใหม่เค้าว่ากันครับ
การลงทุนที่ได้กำไรมากๆ อาจจะเป็นการลงทุนที่ห่วยแตกก็ได้ และเราไปสนใจกับแค่ช่วงเวลาหนึ่งๆ (one point in time) แล้วพบว่าระบบลงทุนของเรานี่มันดี เพราะทำกำไรได้มาก แต่จริงๆ อาจจจะฟลุ๊กก็ได้ ในการลงทุนที่ดี สิ่งที่ต้องสนใจไม่แพ้ผลกำไร ก็คือ “ความเสี่ยง” ครับ portfolio ที่ดีจะต้องให้น้ำหนักกับเรื่องนี้ให้มาก

วันนี้เราเลยจะมาดูเรื่องผลกระทบของการ “Rebalance Portfolio” กันครับ โดยตัวอย่างที่ผมเลือกมาเพื่อให้เราเห็นว่า การลงทุนที่ดีที่สุดไม่จำเป็นต้องทำกำไรมากที่สุด และทำไมต้อง Rebalanced Portfolio กันครับ
import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt'
import pandas as pd
%matplotlib inline
plt.style.use("ggplot")
ก่อนอื่นดึง library ที่ต้องใช้มาก่อน ก็ตัวเดิมๆทั้งนั้น
start = "2020-01-01"
end = "2021-12-30"
asset1 = "GOOG"
asset2 = "MMM"
asset1_close = yf.download(asset1, start=start, end=end)["Close"]
asset2_close = yf.download(asset2, start=start, end=end)["Close"]
ดึงข้อมูลหุ้น สองตัว Google และ 3M อันนี้เราจะเลือกสุ่มๆนะครับ และเพื่อความเรียบง่าย ผมจะใช้แค่หุ้น 2 ตัวในพอร์ตเป็นตัวอย่าง เราจะสมมุติว่าการถือหุ้นสองตัวนี้จะแบบ equal weight จะดีกับ risk profile ก็แล้วกันครับ
asset1_rets = asset1_close.pct_change().dropna()
asset2_rets = asset2_close.pct_change().dropna()
หา return ของหุ้นทั้ง 2 ตัว โดยใช้ simple return เก็บไว้ก่อน จากนั้นลองดูหน้าตาของหุ้นสองตัว
plt.figure(figsize=(15,10))
asset1_close.plot(label = asset1)
asset2_close.plot(label = asset2)
plt.legend()
plt.title("Closing price");

มองจากสายตามันไม่น่าจะใช่หุ้นที่ดีที่เราควรเอามาทำ portfolio หรอกครับเพราะ correlation น่าจะสูง เราสามารถดูได้จากเรื่อง correlationที่เคยเขียนไปอย่าง ทำไมต้อง uncorrelated ที่เราเคยเขียนไปและที่สอนในคอร์ส python for finance การจัดหุ้น correlation สูงไว้ในพอร์ตไม่ใช่เรื่องดี

มาถึงตรงนี้ผมหลอกไปนิดหนึงครับ correlation สูงไม่ใช่เรื่องดีนั้นจริง แต่นี่มันราคาปิดครับ มันหลอกตาได้ ถ้าเอามาหา correlation มันจะสูงเกือบตลอดนั่นแหละ ถ้าจะหา correlation จริงๆก็อย่าลืมไปใช้ return แทนนะครับ
อย่างไรก็ตามดูราคาปิดเทียบกันอาจจะไม่เห็นภาพมากนัก ผมจะ normalize ให้มันเสกลเดียวกันและดูผลงานของหุ้นสองตัวนี้
plt.figure(figsize=(15,10))
(asset1_close/asset1_close.iloc[0]).plot(label = asset1)
(asset2_close/asset2_close.iloc[0]).plot(label = asset2)
plt.legend()
plt.title("Normalize price ");

เมื่อผ่านการ normalize แล้วจะเห็นภาพที่แท้จริงได้ดีขึ้น จากนั้นเราจะหา correlation จาก return กัน
print("correlation: ", np.corrcoef(asset1_rets, asset2_rets)[1][0])

ค่อนข้างไปในทางสูงนิดหน่อยครับ แต่นั่นไม่ใช่ประเด็นของบทความนี้ สมมุติว่าสมุติฐานตั้งต้น(ควรจะมาจากการ research )เราต้องการ การถือหุ้นสองตัวนี้ที่น้ำหนักเท่ากันอย่างละ 50 เปอร์เซ็นของพอร์ต จะทำให้เราได้ risk/reward ที่เราต้องการ
df_rets = np.array([asset1_rets, asset2_rets])
print("returns shape: ", df_rets.shape)
print(df_rets)
df_close = np.array([asset1_close, asset2_close])
print("close shape: ", df_close.shape)
print(df_close)

จะทำแบบนั้นได้เรามาสร้าง array เก็บ return และราคา close ของหุ้นทั้ง 2 ตัวกันก่อน

Rebalance หุ้นแบบรายวัน
เนื่องจากเป็นการทดลอง เราจะมาทำการ rebalance หุ้นกันทุกวันครับ กล่าวคือทุกวันเราต้องมีหุ้นจำนวนเท่ากันใน portfolio ถ้าเรามีหุ้น A ที่ราคา 100 บาท และ หุ้น B ที่ราคา 100 บาทและเรามีเงิน 1000 บาท เราจะซื้อ หุ้น A และ B อย่างละ 5 หุ้น ถ้า หุ้นตัวใดตัวหนึงมีการเปลี่ยนแปลงทางราคา เช่น วันที่ 2 หุ้น A ราคา 100 บาทเท่าเดิม แต่หุ้น B ไป 250 บาท เราจะลดจำนวนหุ้น B ลง และไปซื้อหุ้น A เพิ่มให้มีจำนวนเท่ากัน
แต่อย่าไปทำ Rebalance ทุกวันจริงๆนะครับ น่าจะพังกว่ารุ่งเพราะจะเสียค่าคอมมิชชั่นโดยใช่เหตุ ควรกำหนดเป็นช่วงๆที่ต้องการดีกว่าเช่น ทุก 3 เดือน 6 เดือน เป็นต้น
โอเคครับ มาเริ่มโค้ดกันต่อ ผมจะกำหนดน้ำหนักของหุ้นในพอร์ตให้เท่ากันและเงินลงทุนตั้งต้น 100000 เหรียญ
port_value = 100000
asset1_weight = 0.5
asset2_weight = 0.5
port_weight = np.array([asset1_weight, asset2_weight])
plt.figure(figsize=(15,10))
plt.plot(np.cumprod(1+np.dot(port_weight, df_rets)) * port_value, label="balance")
plt.title("Portfolio Return");

เนื่องจากเป็น simple return เราจึงไม่สามารถคำนวณโดยการ sum ได้ ต้องใช้ np.cumprod(1+np.dot(port_weight, df_rets)) โดย np.dot(port_weight, df_rets) จะได้ return ของหุ้นตามสัดส่วน เรา +1 เพื่อให้อยู่ในรูปแบบที่สามารถใช้คูณแบบสะสม cumulative product ได้

สร้าง Portfolio ที่ไม่มีการ Rebalanced เพิ่อเปรียบเทียบ
ในส่วนนี้ผมจะสร้างพอร์ตที่ไม่มีการ rebalance เลย คือ ซื้อณ วันแรก แล้วปล่อยลืมไปเลย แล้วค่อยมาวัดผลกับแบบ Rebalance ทุกวันครับ
asset1_share = (port_value/2)/ asset1_close.iloc[0]
asset2_share = (port_value/2)/ asset2_close.iloc[0]
print("asset 1 share: ", asset1_share)
print("asset 2 share: ", asset2_share)

ก่อนอื่นเราจะหาว่า เงินจำนวนครึ่งหนึงของพอร์ตเรา จะซื้อหุ้น Google และ 3M ได้อย่างละกี่หุ้น โดยจะคิดที่ราคาวันแรกของการทดสอบ จะเห็นว่าเราจะซื้อกูเกิลได้ประมาณ 731 หุ้น และ 3m 277 หุ้น จริงๆเศษส่วนควรปัดนะครับ แต่ในที่นี้ผมจะไม่ปัดเพื่อการศึกษาล้วนๆ
port_share = np.array([asset1_share, asset2_share])
buy_n_hold = np.dot(port_share, df_close)
daily_rebalanced = np.cumprod(1+np.dot(port_weight, df_rets)) * port_value
plt.figure(figsize=(15,10))
plt.plot(buy_n_hold, label="Buy and Hold Portfolio")
plt.plot(daily_rebalanced, label="Daily Rebalanecd Portfolio")
plt.legend()
plt.title("Portfolio Return");

ผมคำนวณ return รายวันของทั้งแบบซื้อทีเดียวจบ และ แบบ rebalance รายวันจากนั้นพล๊อมันเปรียบเทียบกัน จะเห็นว่ามันต่างกันพอสมควรเลย ก็เพราะราคาหุ้นมันขึ้นลงต่างกันเยอะ และผลงานแบบ daily rebalance ของเราห่วยกว่าแบบ buy and hold ซะอีกแปลว่าเราไม่ควรทำใช่ไหม?
final_val_daily = daily_rebalanced[-1]
final_val_bnh = buy_n_hold[-1]
print("Daily Realanced final: ", final_val_daily)
print("Buy and Hold final: ", final_val_bnh)

คำตอบคือไม่ครับ พอร์ตที่ดี คือพอร์ตที่กำจัดความเสี่ยงได้ตามแผนตั้งต้นของเรา ไม่ใช่พอร์ตที่กำไรมากที่สุด เพราะไอ้คำว่า *กำไรมากสุด มันเป็นแค่ช่วงหนึงของเวลาครับ มันอาจจะแย่กว่าในระยะยาวก็ได้ เราไม่รู้ แต่เรารู้คือ เรามีแผนและควรทำตามมัน ถ้าเราอยากจะถือ หุ้นอย่างละ 50% มันก็ควรเป็นไปตามนั้น เรามาดูผลสุดท้ายกันดีกว่าว่า หุ้นในพอร์ตแบบไม่มีการ rebalance นั้นเราถือสัดส่วนเท่าไหร่ในวัดสุดท้าย
asset1_last_close = df_close[0][-1]
asset2_last_close = df_close[1][-1]
print("asset 1 percentage: ", (asset1_last_close * asset1_share)/final_val_bnh,"%")
print("asset 2 percentage: ", (asset2_last_close * asset2_share)/final_val_bnh,"%")

ราเอาราคาวันสุดท้าย มาคูณกับจำนวนหุ้นเราซื้อในวันแรก จะพบว่า หุ้น Google มันดันมีสัดส่วน 68% ของพอร์ตเราไปแล้ว ขณะที่ 3M เหลือแค่ 31% กว่าๆเท่านั้นเอง

สุดท้ายนี้ลองมาดูความเสี่ยงของหุ้น 2 ตัวนี้ของเรากันหน่อย
print("Buy and Hold volatility: ", pd.DataFrame(np.dot(port_share, df_close)).pct_change().std()[0]*np.sqrt(252))
print("Daily Rebalanced volatility: ", np.std(np.dot(port_weight, df_rets))*np.sqrt(252))

จากรูปจะเห็นว่า portfolio ที่ไม่มีการ rebalanced นั้นมีความเสี่ยงสูงกว่าอยู่นิดหน่อยครับ เนื่องมาจากตัว
แล้วก็นี่แค่ช่วงเวลา 2 ปี กับหุ้นในพอร์ตแค่ 2 ตัวนะครับ จะเกิดอะไรขึ้นถ้าเรามีหุ้นซัก 10-20 ตัวในพอร์ตแล้วดันมีตัวใดซักตัวหนึง โตมาเกินพอร์ตแบบนี้อาจจะทำลายแผนการ risk/reward ของเราไปเลยก็ได้
ตัวอย่างเช่น เราต้องการมีพอร์ตที่อนุรักษ์นิมยมหน่อย เรามีหุ้น tech ที่คาดหวังจะโตสูงอยู่ 1 ตัว และมี volatility สูง เราอาจจะอยากเอาหุ้นเหวี่ยงต่ำอย่าง food and beverage ที่เป็นหุ้นเชิง defensive อยู่ 4 ตัว
เนื่องจากผมอยากสร้างพอร์ตที่รับความเสี่ยงต่ำ ผมอาจจะให้น้ำหนัก หุ้นในกลุ่ม food and beverage ซัก 60-70% ของ พอร์ต และให้ Tech ซัก 30-40% ก็ได้ ถ้าวันไหนที่ tech มันโตเกินไปเราต้องขายออกครับถ้ายังอยากได้โปรไฟล์ความเสี่ยงแบบเดิม เพราะไม่งั้นเราก็ไม่สามารถคุมความเสี่ยงตามแผนเดิมได้อีกแล้ว