
บทนำ: ไขปริศนา “หุ้นปันผลสูงตลอดกาล” ในยุคเทคโนโลยีการลงทุน
ในโลกของการลงทุน วลีที่ว่า “หุ้นปันผลสูงตลอดกาล” เป็นเหมือนยอดปรารถนาของนักลงทุนสายเน้นคุณค่า (Value Investor) และสายสร้างรายได้ passive income แต่ในยุคที่เทคโนโลยีทางการเงิน (FinTech) และเครื่องมือวิเคราะห์ข้อมูลขั้นสูงเข้ามามีบทบาท คำถามสำคัญคือ “หุ้นปันผลสูงตลอดกาล” เป็นเพียงตำนานที่ถูกเล่าขาน หรือเป็นกลยุทธ์ที่สามารถพิสูจน์ได้ด้วยข้อมูลและโค้ด?
บทความนี้จะพาคุณดำดิ่งสู่การวิเคราะห์เชิงลึก โดยใช้เทคโนโลยีทางการเงินสมัยใหม่ ไม่ว่าจะเป็นการสคริปปิ้งข้อมูล (Web Scraping) เพื่อดึงข้อมูลปันผลย้อนหลัง การใช้ Python วิเคราะห์อัตราการเติบโตของเงินปันผล (Dividend Growth Rate) และการใช้ Machine Learning เพื่อคัดกรองหุ้นที่มีแนวโน้มจ่ายปันผลสม่ำเสมอ เราจะไม่พูดถึงแค่ทฤษฎี แต่จะลงมือปฏิบัติจริงด้วยโค้ดที่คุณสามารถนำไปปรับใช้ได้ทันที
ก่อนอื่น เราต้องเข้าใจก่อนว่า “หุ้นปันผลสูงตลอดกาล” ในบริบทของเทคโนโลยี หมายถึงหุ้นที่สามารถรักษาหรือเพิ่มอัตราการจ่ายเงินปันผล (Dividend Per Share: DPS) ได้อย่างต่อเนื่อง แม้จะผ่านพ้นวิกฤตเศรษฐกิจหรือการเปลี่ยนแปลงทางเทคโนโลยีครั้งใหญ่ ซึ่งต้องอาศัยปัจจัยพื้นฐานที่แข็งแกร่งและกระแสเงินสดอิสระ (Free Cash Flow) ที่มั่นคง
เราจะใช้ข้อมูลจากแหล่งเปิดอย่าง Yahoo Finance และ SET (ตลาดหลักทรัพย์แห่งประเทศไทย) ผ่าน API และ Web Scraping เพื่อสร้างแบบจำลองการประเมินมูลค่าแบบ DDM (Dividend Discount Model) และเปรียบเทียบกับหุ้นปันผลสูงทั่วไป เพื่อให้เห็นภาพชัดเจนว่าความแตกต่างอยู่ตรงไหน
1. ฐานข้อมูลและเครื่องมือเทคโนโลยีที่จำเป็น
ก่อนที่เราจะเริ่มเขียนโค้ด เราต้องเตรียม “คลังแสง” ทางเทคโนโลยีเสียก่อน การทำงานกับข้อมูลหุ้นปันผลสูงจำเป็นต้องมีชุดเครื่องมือที่ครบถ้วน ตั้งแต่การดึงข้อมูล การทำความสะอาดข้อมูล ไปจนถึงการวิเคราะห์เชิงสถิติ
1.1 แหล่งข้อมูลหลัก (Data Sources)
- Yahoo Finance (yfinance): ไลบรารี Python ยอดนิยมสำหรับดึงข้อมูลราคาหุ้นและเงินปันผลย้อนหลัง รองรับตลาดหุ้นทั่วโลก รวมถึง SET
- SET Smart API / SET Trade: สำหรับข้อมูลเชิงลึกของตลาดหุ้นไทย เช่น งบการเงิน อัตราส่วนทางการเงิน และนโยบายการจ่ายปันผล
- Morningstar / Investing.com: สำหรับข้อมูล Dividend History และ Dividend Yield แบบละเอียด
- Google Finance (ผ่าน gspread): สำหรับการเชื่อมต่อข้อมูลเข้าสู่ Google Sheets เพื่อการทำงานร่วมกันเป็นทีม
1.2 ไลบรารี Python ที่จำเป็น
# ไลบรารีหลักสำหรับการวิเคราะห์
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')
# สำหรับการคำนวณทางสถิติและการเงิน
from scipy import stats
import statsmodels.api as sm
# สำหรับ Machine Learning (กรณีต้องการพยากรณ์)
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, r2_score
1.3 การติดตั้งและตั้งค่า Environment
เราขอแนะนำให้ใช้ Google Colab หรือ Jupyter Notebook สำหรับการทำงานนี้ เนื่องจากง่ายต่อการแสดงผลกราฟและตาราง การติดตั้งไลบรารีสามารถทำได้ด้วยคำสั่ง pip install ตามปกติ
# ติดตั้งไลบรารีที่จำเป็น (รันใน Terminal หรือ Notebook Cell)
!pip install yfinance pandas numpy matplotlib seaborn scipy statsmodels scikit-learn
เมื่อเตรียมเครื่องมือพร้อมแล้ว เราจะเริ่มต้นด้วยการดึงข้อมูลหุ้นปันผลสูงที่ขึ้นชื่อในตลาดไทย เช่น ADVANC, CPALL, SCC และเปรียบเทียบกับหุ้นปันผลสูงในตลาดสหรัฐ เช่น KO (Coca-Cola), JNJ (Johnson & Johnson) และ T (AT&T) เพื่อดูความแตกต่างของพฤติกรรมการจ่ายปันผล
2. การดึงข้อมูลเงินปันผลย้อนหลังด้วย Python (Web Scraping & API)
หัวใจสำคัญของการวิเคราะห์ “หุ้นปันผลสูงตลอดกาล” คือข้อมูลในอดีตที่ยาวนานเพียงพอ เราจะใช้ yfinance ซึ่งเป็น wrapper ของ Yahoo Finance API ในการดึงข้อมูล Dividend History ย้อนหลังสูงสุด 20-30 ปี
2.1 การดึงข้อมูลหุ้นไทย (SET) ผ่าน yfinance
ข้อควรรู้: หุ้นไทยใน Yahoo Finance จะมี suffix “.BK” ต่อท้าย เช่น ADVANC.BK, CPALL.BK
# กำหนดรายชื่อหุ้นที่สนใจ
tickers = ['ADVANC.BK', 'CPALL.BK', 'SCC.BK', 'PTT.BK', 'KBANK.BK']
# สร้าง DataFrame เพื่อเก็บข้อมูลเงินปันผล
dividend_data = pd.DataFrame()
for ticker in tickers:
stock = yf.Ticker(ticker)
# ดึงประวัติการจ่ายปันผล (Dividend History)
divs = stock.dividends
# แปลงเป็น DataFrame และเพิ่มคอลัมน์ชื่อหุ้น
temp_df = divs.to_frame(name='Dividend')
temp_df['Ticker'] = ticker
dividend_data = pd.concat([dividend_data, temp_df])
# แสดงข้อมูลตัวอย่าง
print(dividend_data.head(10))
print(f"จำนวนข้อมูลทั้งหมด: {len(dividend_data)} แถว")
2.2 การวิเคราะห์ Dividend Growth Rate (DGR)
เมื่อได้ข้อมูลมาแล้ว เราต้องคำนวณอัตราการเติบโตของเงินปันผลต่อปี (CAGR) เพื่อดูว่าหุ้นนั้นสามารถเพิ่มปันผลได้สม่ำเสมอหรือไม่
# ฟังก์ชันคำนวณ Dividend CAGR
def calculate_dgr(ticker, years=10):
stock = yf.Ticker(ticker)
divs = stock.dividends
# เลือกข้อมูลเฉพาะช่วง 10 ปีล่าสุด
cutoff_date = datetime.now() - timedelta(days=years*365)
recent_divs = divs[divs.index >= cutoff_date]
if len(recent_divs) < 2:
return None
# หาเงินปันผลรวมต่อปี (Annual Dividend)
annual_divs = recent_divs.resample('Y').sum()
if len(annual_divs) < 2:
return None
# คำนวณ CAGR
start_value = annual_divs.iloc[0]
end_value = annual_divs.iloc[-1]
num_years = len(annual_divs) - 1
if start_value > 0 and num_years > 0:
cagr = (end_value / start_value) ** (1/num_years) - 1
return cagr * 100 # แปลงเป็นเปอร์เซ็นต์
else:
return None
# ทดสอบกับหุ้น ADVANC
dgr_advanc = calculate_dgr('ADVANC.BK', years=10)
print(f"Dividend CAGR (10 ปี) ของ ADVANC: {dgr_advanc:.2f}%")
2.3 การสร้างตารางเปรียบเทียบหุ้นปันผลสูง
เราจะสร้างตารางที่แสดงข้อมูลสำคัญของแต่ละหุ้น เพื่อให้เห็นภาพรวมว่าหุ้นไหนมีคุณสมบัติ “ตลอดกาล” มากที่สุด
# ฟังก์ชันรวบรวมข้อมูลหลาย ๆ ด้าน
def get_dividend_summary(ticker):
stock = yf.Ticker(ticker)
info = stock.info
divs = stock.dividends
annual_divs = divs.resample('Y').sum() if len(divs) > 0 else pd.Series(dtype='float64')
# คำนวณ Dividend Yield (ปัจจุบัน)
current_price = info.get('currentPrice', info.get('regularMarketPrice', None))
latest_annual_div = annual_divs.iloc[-1] if len(annual_divs) > 0 else 0
div_yield = (latest_annual_div / current_price * 100) if current_price and latest_annual_div > 0 else None
# คำนวณ DGR 5 ปี และ 10 ปี
dgr_5 = calculate_dgr(ticker, years=5)
dgr_10 = calculate_dgr(ticker, years=10)
# จำนวนปีที่จ่ายปันผลติดต่อกัน
consecutive_years = len(annual_divs[annual_divs > 0]) if len(annual_divs) > 0 else 0
return {
'Ticker': ticker,
'ชื่อบริษัท': info.get('longName', 'N/A'),
'ราคาปัจจุบัน': current_price,
'Dividend Yield (%)': round(div_yield, 2) if div_yield else 'N/A',
'DGR 5 ปี (%)': round(dgr_5, 2) if dgr_5 else 'N/A',
'DGR 10 ปี (%)': round(dgr_10, 2) if dgr_10 else 'N/A',
'ปีที่จ่ายปันผลติดต่อ': consecutive_years,
'Payout Ratio (%)': info.get('payoutRatio', 'N/A')
}
# สร้าง DataFrame สรุป
summary_data = []
for ticker in ['ADVANC.BK', 'CPALL.BK', 'SCC.BK', 'PTT.BK', 'KBANK.BK',
'KO', 'JNJ', 'T', 'PG', 'MCD']:
try:
summary_data.append(get_dividend_summary(ticker))
except Exception as e:
print(f"Error with {ticker}: {e}")
summary_df = pd.DataFrame(summary_data)
print(summary_df.to_string(index=False))
3. การวิเคราะห์เชิงลึกด้วย Dividend Discount Model (DDM)
Dividend Discount Model (DDM) เป็นแบบจำลองที่ใช้ประเมินมูลค่าหุ้นโดยอิงจากกระแสเงินปันผลในอนาคตที่ถูกคิดลดกลับมาปัจจุบัน สำหรับหุ้นปันผลสูงตลอดกาล DDM แบบ Gordon Growth Model (GGM) เป็นเครื่องมือที่เหมาะสมที่สุด
3.1 สูตร Gordon Growth Model
สูตรพื้นฐาน: P = D1 / (r - g)
- P = มูลค่าที่เหมาะสมของหุ้น
- D1 = เงินปันผลที่คาดว่าจะได้รับในปีหน้า
- r = อัตราผลตอบแทนที่ต้องการ (Required Rate of Return)
- g = อัตราการเติบโตของเงินปันผลในระยะยาว (Constant Growth Rate)
3.2 การนำ DDM ไปใช้กับหุ้นไทย
def gordon_growth_model(ticker, required_return=0.09, growth_assumption=0.04):
"""
คำนวณมูลค่าหุ้นด้วย Gordon Growth Model
Parameters:
ticker: ชื่อหุ้น
required_return: อัตราผลตอบแทนที่ต้องการ (default 9%)
growth_assumption: อัตราการเติบโตของปันผลระยะยาว (default 4%)
"""
stock = yf.Ticker(ticker)
info = stock.info
# หาเงินปันผลล่าสุด (D0)
divs = stock.dividends
if len(divs) == 0:
return None
# ใช้เงินปันผลรวมของปีล่าสุด
annual_divs = divs.resample('Y').sum()
if len(annual_divs) == 0:
return None
d0 = annual_divs.iloc[-1] # เงินปันผลปัจจุบัน
d1 = d0 * (1 + growth_assumption) # เงินปันผลปีหน้า
# ตรวจสอบว่าอัตราการเติบโตน้อยกว่าอัตราผลตอบแทนที่ต้องการ
if growth_assumption >= required_return:
return "Error: g must be less than r"
# คำนวณมูลค่าที่เหมาะสม
fair_value = d1 / (required_return - growth_assumption)
# ราคาปัจจุบัน
current_price = info.get('currentPrice', info.get('regularMarketPrice', None))
# คำนวณ Margin of Safety
if current_price and current_price > 0:
margin_of_safety = ((fair_value - current_price) / fair_value) * 100
else:
margin_of_safety = None
return {
'Ticker': ticker,
'D0 (บาท)': round(d0, 2),
'D1 (บาท)': round(d1, 2),
'Fair Value (บาท)': round(fair_value, 2),
'Current Price (บาท)': current_price,
'Margin of Safety (%)': round(margin_of_safety, 2) if margin_of_safety else 'N/A',
'r (Required Return)': f"{required_return*100}%",
'g (Growth Assumption)': f"{growth_assumption*100}%"
}
# ทดสอบกับ ADVANC
result = gordon_growth_model('ADVANC.BK', required_return=0.09, growth_assumption=0.05)
print(result)
3.3 การวิเคราะห์ความอ่อนไหว (Sensitivity Analysis)
เนื่องจาก DDM ขึ้นอยู่กับสมมติฐานของ r และ g อย่างมาก เราจึงควรทำ Sensitivity Analysis เพื่อดูว่ามูลค่าหุ้นเปลี่ยนไปอย่างไรเมื่อเปลี่ยนสมมติฐาน
def sensitivity_analysis(ticker):
stock = yf.Ticker(ticker)
divs = stock.dividends
annual_divs = divs.resample('Y').sum()
d0 = annual_divs.iloc[-1]
# สร้างช่วงของ r และ g
r_range = np.arange(0.07, 0.13, 0.005) # 7% ถึง 12%
g_range = np.arange(0.03, 0.07, 0.005) # 3% ถึง 6%
# สร้าง DataFrame สำหรับผลลัพธ์
sensitivity_df = pd.DataFrame(index=[f"g={g:.1%}" for g in g_range],
columns=[f"r={r:.1%}" for r in r_range])
for i, g in enumerate(g_range):
for j, r in enumerate(r_range):
if g < r:
d1 = d0 * (1 + g)
fair_value = d1 / (r - g)
sensitivity_df.iloc[i, j] = round(fair_value, 2)
else:
sensitivity_df.iloc[i, j] = "N/A"
return sensitivity_df
# ทดสอบ
sensitivity_df = sensitivity_analysis('ADVANC.BK')
print(sensitivity_df)
4. การใช้ Machine Learning เพื่อคัดกรองหุ้นปันผลสูงตลอดกาล
การวิเคราะห์ด้วยมือสำหรับหุ้นหลายร้อยตัวเป็นเรื่องยาก เราสามารถใช้ Machine Learning เพื่อสร้างแบบจำลองที่ช่วยคัดกรองหุ้นที่มีแนวโน้มจะเป็น “ปันผลสูงตลอดกาล” โดยอิงจากตัวแปรทางปัจจัยพื้นฐาน
4.1 การสร้าง Features (ตัวแปรอิสระ)
ตัวแปรที่เราจะใช้ในการทำนาย ได้แก่:
- Dividend Yield (ปัจจุบัน)
- Payout Ratio (อัตราการจ่ายปันผล)
- Debt to Equity Ratio (D/E)
- Return on Equity (ROE)
- Free Cash Flow Yield (FCF Yield)
- Revenue Growth (3 ปี)
- Earnings Stability (ความสม่ำเสมอของกำไร)
# ฟังก์ชันดึงข้อมูลปัจจัยพื้นฐาน
def get_fundamental_features(ticker):
stock = yf.Ticker(ticker)
info = stock.info
features = {
'Ticker': ticker,
'Dividend_Yield': info.get('dividendYield', None),
'Payout_Ratio': info.get('payoutRatio', None),
'Debt_to_Equity': info.get('debtToEquity', None),
'ROE': info.get('returnOnEquity', None),
'FCF_Yield': info.get('freeCashflowYield', None),
'Revenue_Growth_3yr': info.get('revenueGrowth', None),
'Earnings_Growth_3yr': info.get('earningsGrowth', None),
'Market_Cap': info.get('marketCap', None),
'Sector': info.get('sector', 'Unknown')
}
return features
# รวบรวมข้อมูลหุ้นหลายตัว
ticker_list = ['ADVANC.BK', 'CPALL.BK', 'SCC.BK', 'PTT.BK', 'KBANK.BK',
'BDMS.BK', 'GPSC.BK', 'MINT.BK', 'TISCO.BK', 'BEM.BK',
'KO', 'JNJ', 'PG', 'MCD', 'T', 'VZ', 'PEP', 'WMT']
feature_data = []
for ticker in ticker_list:
try:
feature_data.append(get_fundamental_features(ticker))
except:
pass
feature_df = pd.DataFrame(feature_data)
print(feature_df.head())
4.2 การสร้างโมเดล Random Forest
เราจะสร้างโมเดลเพื่อทำนายว่า “หุ้นจะสามารถรักษาการจ่ายปันผลได้ต่อเนื่องในอีก 5 ปีข้างหน้าหรือไม่” โดยใช้ข้อมูลในอดีตเป็น Training Set
# เตรียมข้อมูลสำหรับ Machine Learning
# สมมติว่าเรามีข้อมูล Dividend Growth Rate ย้อนหลัง 10 ปีเป็น Target Variable
# โดย Target = 1 ถ้า DGR 5 ปี > 0% (จ่ายปันผลเพิ่มขึ้น) และ = 0 ถ้า DGR <= 0%
# สร้าง Target Variable
def create_target(ticker):
dgr_5 = calculate_dgr(ticker, years=5)
if dgr_5 is None:
return None
return 1 if dgr_5 > 0 else 0
feature_df['Target'] = feature_df['Ticker'].apply(create_target)
# ลบแถวที่มีค่า NaN
feature_df_clean = feature_df.dropna(subset=['Target', 'Dividend_Yield', 'Payout_Ratio',
'Debt_to_Equity', 'ROE', 'FCF_Yield'])
# เลือก Features และ Target
X = feature_df_clean[['Dividend_Yield', 'Payout_Ratio', 'Debt_to_Equity',
'ROE', 'FCF_Yield']]
y = feature_df_clean['Target']
# แบ่งข้อมูล Train/Test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# สร้างโมเดล Random Forest
rf_model = RandomForestRegressor(n_estimators=100, max_depth=5, random_state=42)
rf_model.fit(X_train, y_train)
# ทำนาย
y_pred = rf_model.predict(X_test)
y_pred_class = (y_pred > 0.5).astype(int)
# ประเมินผล
accuracy = (y_pred_class == y_test).mean()
print(f"Accuracy: {accuracy:.2%}")
# แสดง Feature Importance
feature_importance = pd.DataFrame({
'Feature': X.columns,
'Importance': rf_model.feature_importances_
}).sort_values('Importance', ascending=False)
print(feature_importance)
4.3 การนำโมเดลไปใช้คัดกรองหุ้นจริง
เมื่อโมเดลพร้อม เราสามารถนำไปใช้กับหุ้นใน SET100 เพื่อคัดกรองหุ้นที่มีแนวโน้มจะเป็น “ปันผลสูงตลอดกาล”
# ฟังก์ชันทำนายหุ้นใหม่
def predict_dividend_quality(ticker):
features = get_fundamental_features(ticker)
if any(v is None for v in [features['Dividend_Yield'], features['Payout_Ratio'],
features['Debt_to_Equity'], features['ROE'],
features['FCF_Yield']]):
return {'Ticker': ticker, 'Prediction': 'Insufficient Data'}
input_data = pd.DataFrame([[
features['Dividend_Yield'],
features['Payout_Ratio'],
features['Debt_to_Equity'],
features['ROE'],
features['FCF_Yield']
]], columns=['Dividend_Yield', 'Payout_Ratio', 'Debt_to_Equity', 'ROE', 'FCF_Yield'])
prob = rf_model.predict(input_data)[0]
quality = 'High' if prob > 0.7 else ('Medium' if prob > 0.4 else 'Low')
return {
'Ticker': ticker,
'Probability': round(prob, 3),
'Quality': quality
}
# ทดสอบกับหุ้นตัวอย่าง
test_tickers = ['ADVANC.BK', 'CPALL.BK', 'SCC.BK', 'PTT.BK', 'KBANK.BK',
'BJC.BK', 'HMPRO.BK', 'TRUE.BK']
predictions = [predict_dividend_quality(t) for t in test_tickers]
pred_df = pd.DataFrame(predictions)
print(pred_df)
5. ตารางเปรียบเทียบ: หุ้นปันผลสูงทั่วไป vs หุ้นปันผลสูงตลอดกาล
เพื่อให้เห็นความแตกต่างอย่างชัดเจน เราจะสร้างตารางเปรียบเทียบระหว่างหุ้นที่จ่ายปันผลสูงแต่ไม่สม่ำเสมอ กับหุ้นที่มีประวัติการเพิ่มปันผลอย่างต่อเนื่อง
| คุณสมบัติ | หุ้นปันผลสูงทั่วไป | หุ้นปันผลสูงตลอดกาล |
|---|---|---|
| Dividend Yield | สูงมาก (6-10%) มักเป็นสัญญาณอันตราย | ปานกลางถึงสูง (3-5%) แต่ยั่งยืน |
| Dividend Growth Rate (10 ปี) | ผันผวน ติดลบบ่อย | เพิ่มขึ้นสม่ำเสมอ 5-10% ต่อปี |
| Payout Ratio | สูงเกิน 100% (จ่ายเกินกำไร) | 50-70% เหลือไว้ลงทุนต่อ |
| Debt to Equity | สูง > 1.5x (เสี่ยง) | ต่ำ < 0.8x (ปลอดภัย) |
| Free Cash Flow Yield | ต่ำหรือติดลบ | สูง > 4% |
| ความสม่ำเสมอของกำไร | ขึ้นลงตามเศรษฐกิจ | เติบโตสม่ำเสมอ 10+ ปี |
| ตัวอย่างหุ้น | T (AT&T), VZ (Verizon) ในอดีต | KO (Coca-Cola), JNJ, ADVANC |
| ความเสี่ยง | ลดปันผล หรือตัดปันผลกะทันหัน | ต่ำมาก (แต่ราคาอาจขึ้นช้า) |
| เหมาะกับใคร | นักเก็งกำไรระยะสั้น | นักลงทุนระยะยาว สร้าง Passive Income |
6. Best Practices และ Real-World Use Cases
6.1 การใช้เทคโนโลยีติดตาม Dividend Calendar
นักลงทุนสามารถสร้างระบบแจ้งเตือนอัตโนมัติเมื่อมีประกาศจ่ายปันผล โดยใช้ Google Calendar API ร่วมกับ Web Scraping จากเว็บไซต์ SET หรือบริษัทหลักทรัพย์
# ตัวอย่างโค้ดสำหรับสร้าง Dividend Alert (Conceptual)
# ใช้ schedule library เพื่อรันทุกวัน
import schedule
import time
from datetime import date
def check_dividend_announcements():
# สมมติว่ามีฟังก์ชัน scrape_dividend_calendar() ที่ดึงข้อมูลจากเว็บ
today = date.today()
upcoming_dividends = scrape_dividend_calendar(date_from=today, date_to=today+timedelta(days=30))
for div in upcoming_dividends:
if div['ex_date'] == today:
send_notification(f"วันนี้ XD: {div['ticker']} ปันผล {div['amount']} บาท")
elif div['pay_date'] == today:
send_notification(f"วันนี้รับปันผล: {div['ticker']} จำนวน {div['amount']} บาท")
# กำหนดให้รันทุกวันเวลา 08:00 น.
schedule.every().day.at("08:00").do(check_dividend_announcements)
# while True:
# schedule.run_pending()
# time.sleep(60)
6.2 การสร้าง Portfolio Rebalancing Algorithm
สำหรับนักลงทุนที่ถือหุ้นปันผลหลายตัว การปรับพอร์ตโดยอัตโนมัติเมื่ออัตราส่วนเปลี่ยนไปเป็นสิ่งสำคัญ เราสามารถใช้ Python สร้างระบบที่แนะนำการซื้อขายตามสัดส่วนที่กำหนด
class DividendPortfolioRebalancer:
def __init__(self, target_weights, tickers):
"""
target_weights: dict เช่น {'ADVANC.BK': 0.25, 'CPALL.BK': 0.25, ...}
tickers: list ของชื่อหุ้น
"""
self.target_weights = target_weights
self.tickers = tickers
self.current_prices = {}
def update_prices(self):
for ticker in self.tickers:
stock = yf.Ticker(ticker)
self.current_prices[ticker] = stock.history(period='1d')['Close'].iloc[-1]
def calculate_current_weights(self, portfolio_value, holdings):
"""
holdings: dict เช่น {'ADVANC.BK': 1000, 'CPALL.BK': 500}
"""
current_weights = {}
for ticker, shares in holdings.items():
value = shares * self.current_prices[ticker]
current_weights[ticker] = value / portfolio_value
return current_weights
def generate_rebalance_orders(self, holdings, portfolio_value, threshold=0.05):
"""
threshold: เกณฑ์ที่ยอมให้คลาดเคลื่อนได้ (5%)
"""
self.update_prices()
current_weights = self.calculate_current_weights(portfolio_value, holdings)
orders = []
for ticker in self.tickers:
target = self.target_weights[ticker]
current = current_weights.get(ticker, 0)
if abs(current - target) > threshold:
# ต้องการซื้อเพิ่มหรือขายออก
desired_value = target * portfolio_value
current_value = current * portfolio_value
difference = desired_value - current_value
if difference > 0:
action = 'BUY'
shares_to_trade = difference // self.current_prices[ticker]
else:
action = 'SELL'
shares_to_trade = abs(difference) // self.current_prices[ticker]
orders.append({
'Ticker': ticker,
'Action': action,
'Shares': int(shares_to_trade),
'Estimated Value': round(shares_to_trade * self.current_prices[ticker], 2)
})
return orders
# ตัวอย่างการใช้งาน
rebalancer = DividendPortfolioRebalancer(
target_weights={'ADVANC.BK': 0.30, 'CPALL.BK': 0.25, 'SCC.BK': 0.25, 'PTT.BK': 0.20},
tickers=['ADVANC.BK', 'CPALL.BK', 'SCC.BK', 'PTT.BK']
)
holdings = {'ADVANC.BK': 1500, 'CPALL.BK': 800, 'SCC.BK': 600, 'PTT.BK': 1200}
portfolio_value = 500000 # สมมติ
orders = rebalancer.generate_rebalance_orders(holdings, portfolio_value)
print("Rebalance Orders:", orders)
6.3 กรณีศึกษา: การใช้ AI วิเคราะห์นโยบายปันผลของบริษัท
ในโลกจริง บริษัทอย่าง Procter & Gamble (PG) มีประวัติการเพิ่มปันผลมากว่า 65 ปีติดต่อกัน (Dividend Aristocrat) เราสามารถใช้ Natural Language Processing (NLP) วิเคราะห์คำพูดของ CEO ในรายงานประจำปี เพื่อดูแนวโน้มการรักษานโยบายปันผล
ตัวอย่างการวิเคราะห์ sentiment ของ Annual Report:
# ตัวอย่างการใช้ TextBlob หรือ VADER สำหรับวิเคราะห์ Sentiment
from textblob import TextBlob
import requests
from bs4 import BeautifulSoup
def analyze_dividend_sentiment(annual_report_url):
# ดึงเนื้อหาจาก URL
response = requests.get(annual_report_url)
soup = BeautifulSoup(response.text, 'html.parser')
text = soup.get_text()
# ค้นหาข้อความที่เกี่ยวข้องกับปันผล
dividend_sentences = []
for sentence in text.split('.'):
if 'dividend' in sentence.lower() or 'ปันผล' in sentence:
dividend_sentences.append(sentence)
# วิเคราะห์ Sentiment
positive_count = 0
total_sentences = len(dividend_sentences)
for sentence in dividend_sentences:
blob = TextBlob(sentence)
if blob.sentiment.polarity > 0.1:
positive_count += 1
sentiment_score = positive_count / total_sentences if total_sentences > 0 else 0
return {
'Total Dividend Mentions': total_sentences,
'Positive Sentiment Ratio': round(sentiment_score, 2),
'Verdict': 'Positive Outlook' if sentiment_score > 0.6 else 'Neutral' if sentiment_score > 0.3 else 'Negative'
}
# ตัวอย่างการใช้งาน (สมมติ URL)
# result = analyze_dividend_sentiment('https://example.com/annual-report-2023')
# print(result)
7. ข้อควรระวังและข้อจำกัดทางเทคนิค
แม้ว่าเทคโนโลยีจะช่วยให้เราวิเคราะห์หุ้นปันผลสูงได้อย่างมีประสิทธิภาพ แต่ก็มีข้อจำกัดที่ต้องตระหนัก:
7.1 ข้อจำกัดของข้อมูล
- Data Quality: ข้อมูลจาก Yahoo Finance อาจไม่สมบูรณ์สำหรับหุ้นไทยบางตัว โดยเฉพาะข้อมูลย้อนหลังก่อนปี 2010
- Survivorship Bias: ข้อมูลที่เราเห็นเป็นเฉพาะหุ้นที่รอดมาได้จนถึงปัจจุบัน หุ้นที่ล้มละลายหรือถูกเทกโอเวอร์จะถูกลบออกจากฐานข้อมูล
- Dividend Adjustment: การปรับราค