เทคนิคการวิเคราะห์หุ้น — Fundamental & Technical Analysis
การวิเคราะห์หุ้นเป็นทักษะสำคัญสำหรับนักลงทุนทุกระดับ แบ่งเป็น 2 แนวทางหลักคือ Fundamental Analysis (วิเคราะห์ปัจจัยพื้นฐาน) ที่ดูงบการเงิน กำไร หนี้สิน และมูลค่าที่แท้จริง กับ Technical Analysis (วิเคราะห์ทางเทคนิค) ที่ดูกราฟราคา ปริมาณการซื้อขาย และ indicators ทางสถิติ นักลงทุนมืออาชีพมักใช้ทั้งสองแนวทางร่วมกัน บทความนี้อธิบายเทคนิคการวิเคราะห์หุ้นครบทั้ง FA และ TA พร้อม Python code สำหรับวิเคราะห์อัตโนมัติ
Fundamental Analysis (FA)
# fundamental.py — Fundamental Analysis tools
import json
class FundamentalAnalysis:
FINANCIAL_RATIOS = {
"pe_ratio": {
"name": "P/E Ratio (Price to Earnings)",
"formula": "ราคาหุ้น / กำไรต่อหุ้น (EPS)",
"interpretation": "P/E ต่ำ → หุ้นถูก (อาจ value trap), P/E สูง → หุ้นแพง (อาจ growth stock)",
"benchmark": "SET average ~15-20x, ดูเทียบกับ industry",
},
"pb_ratio": {
"name": "P/BV Ratio (Price to Book Value)",
"formula": "ราคาหุ้น / มูลค่าทางบัญชีต่อหุ้น",
"interpretation": "P/BV < 1 → ราคาต่ำกว่ามูลค่าทางบัญชี (อาจเป็นโอกาส)",
"benchmark": "ขึ้นกับ industry — ธนาคาร ~0.5-1.5x, Tech ~3-10x",
},
"roe": {
"name": "ROE (Return on Equity)",
"formula": "กำไรสุทธิ / ส่วนผู้ถือหุ้น × 100%",
"interpretation": "ROE สูง → บริษัทใช้ทุนได้มีประสิทธิภาพ",
"benchmark": "> 15% ถือว่าดี, > 20% ดีมาก",
},
"de_ratio": {
"name": "D/E Ratio (Debt to Equity)",
"formula": "หนี้สินรวม / ส่วนผู้ถือหุ้น",
"interpretation": "D/E สูง → leverage สูง → ความเสี่ยงสูง",
"benchmark": "< 1.0 ปลอดภัย, > 2.0 ต้องระวัง (ขึ้นกับ industry)",
},
"dividend_yield": {
"name": "Dividend Yield",
"formula": "เงินปันผลต่อหุ้น / ราคาหุ้น × 100%",
"interpretation": "Yield สูง → รายได้จากเงินปันผลดี",
"benchmark": "> 3% ถือว่าน่าสนใจ สำหรับตลาดหุ้นไทย",
},
"free_cashflow": {
"name": "Free Cash Flow (FCF)",
"formula": "กระแสเงินสดจากดำเนินงาน - ค่าใช้จ่ายลงทุน",
"interpretation": "FCF เป็นบวก → บริษัทมีเงินสดเหลือจ่ายปันผล/ลงทุน",
},
}
def show_ratios(self):
print("=== Financial Ratios ===\n")
for key, ratio in self.FINANCIAL_RATIOS.items():
print(f"[{ratio['name']}]")
print(f" สูตร: {ratio['formula']}")
print(f" อ่านค่า: {ratio['interpretation']}")
print()
def analyze_stock(self):
print("=== ตัวอย่าง: วิเคราะห์หุ้น EXAMPLE ===")
data = {
"Price": "50 บาท", "EPS": "3.5 บาท", "P/E": "14.3x",
"BV/share": "25 บาท", "P/BV": "2.0x", "ROE": "18%",
"D/E": "0.8x", "Div Yield": "4.2%", "FCF": "5.2B บาท",
}
for key, val in data.items():
print(f" {key:<12}: {val}")
print(f"\n สรุป: P/E ต่ำกว่า market, ROE สูง, D/E ปลอดภัย, Yield ดี → น่าสนใจ")
fa = FundamentalAnalysis()
fa.show_ratios()
fa.analyze_stock()
Technical Analysis (TA)
# technical.py — Technical Analysis indicators
import json
class TechnicalAnalysis:
INDICATORS = {
"moving_average": {
"name": "Moving Average (MA)",
"types": "SMA (Simple), EMA (Exponential), WMA (Weighted)",
"use": "ดู trend — ราคาเหนือ MA = uptrend, ใต้ MA = downtrend",
"popular": "MA 50, MA 200 (Golden Cross/Death Cross)",
},
"rsi": {
"name": "RSI (Relative Strength Index)",
"range": "0-100",
"use": "RSI > 70 = overbought (อาจปรับลง), RSI < 30 = oversold (อาจดีดกลับ)",
"period": "ปกติใช้ 14 periods",
},
"macd": {
"name": "MACD (Moving Average Convergence Divergence)",
"components": "MACD Line, Signal Line, Histogram",
"use": "MACD ตัด Signal ขึ้น = Buy, ตัดลง = Sell",
"settings": "12, 26, 9 (default)",
},
"bollinger": {
"name": "Bollinger Bands",
"components": "Middle (SMA 20), Upper (+2SD), Lower (-2SD)",
"use": "ราคาชน Upper = overbought, ชน Lower = oversold, Squeeze = จะ breakout",
},
"volume": {
"name": "Volume Analysis",
"use": "Volume เพิ่มขณะราคาขึ้น = trend แข็ง, Volume ลดขณะราคาขึ้น = trend อ่อน",
"tools": "OBV (On Balance Volume), Volume Profile",
},
"fibonacci": {
"name": "Fibonacci Retracement",
"levels": "23.6%, 38.2%, 50%, 61.8%, 78.6%",
"use": "หาแนวรับ-แนวต้าน — ราคามักเด้งที่ระดับ Fib",
},
}
def show_indicators(self):
print("=== Technical Indicators ===\n")
for key, ind in self.INDICATORS.items():
print(f"[{ind['name']}]")
print(f" ใช้: {ind['use']}")
print()
ta = TechnicalAnalysis()
ta.show_indicators()
Python Stock Analyzer
# stock_analyzer.py — Python stock analysis tool
import json
import random
class StockAnalyzer:
CODE = """
# analyzer.py — Stock analysis with Python
import yfinance as yf
import pandas as pd
import numpy as np
class StockAnalyzer:
def __init__(self, symbol):
self.symbol = symbol
self.stock = yf.Ticker(symbol)
self.data = self.stock.history(period="1y")
def fundamental(self):
info = self.stock.info
return {
"name": info.get("shortName"),
"pe_ratio": info.get("trailingPE"),
"pb_ratio": info.get("priceToBook"),
"roe": info.get("returnOnEquity"),
"de_ratio": info.get("debtToEquity"),
"dividend_yield": info.get("dividendYield"),
"market_cap": info.get("marketCap"),
"sector": info.get("sector"),
}
def technical(self):
df = self.data.copy()
# Moving Averages
df['SMA_50'] = df['Close'].rolling(50).mean()
df['SMA_200'] = df['Close'].rolling(200).mean()
df['EMA_20'] = df['Close'].ewm(span=20).mean()
# RSI
delta = df['Close'].diff()
gain = delta.where(delta > 0, 0).rolling(14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
rs = gain / loss
df['RSI'] = 100 - (100 / (1 + rs))
# MACD
ema12 = df['Close'].ewm(span=12).mean()
ema26 = df['Close'].ewm(span=26).mean()
df['MACD'] = ema12 - ema26
df['Signal'] = df['MACD'].ewm(span=9).mean()
df['Histogram'] = df['MACD'] - df['Signal']
# Bollinger Bands
sma20 = df['Close'].rolling(20).mean()
std20 = df['Close'].rolling(20).std()
df['BB_Upper'] = sma20 + 2 * std20
df['BB_Lower'] = sma20 - 2 * std20
latest = df.iloc[-1]
return {
"price": latest['Close'],
"sma_50": latest['SMA_50'],
"sma_200": latest['SMA_200'],
"rsi": latest['RSI'],
"macd": latest['MACD'],
"signal": latest['Signal'],
"bb_upper": latest['BB_Upper'],
"bb_lower": latest['BB_Lower'],
"trend": "Uptrend" if latest['Close'] > latest['SMA_50'] else "Downtrend",
}
def recommendation(self):
fa = self.fundamental()
ta = self.technical()
score = 0
reasons = []
if fa.get('pe_ratio') and fa['pe_ratio'] < 15:
score += 1; reasons.append("P/E ต่ำ (value)")
if fa.get('roe') and fa['roe'] > 0.15:
score += 1; reasons.append("ROE สูง")
if ta['rsi'] < 30:
score += 1; reasons.append("RSI oversold")
if ta['trend'] == 'Uptrend':
score += 1; reasons.append("Uptrend")
if ta['macd'] > ta['signal']:
score += 1; reasons.append("MACD bullish")
if score >= 4:
return "Strong Buy", reasons
elif score >= 3:
return "Buy", reasons
elif score >= 2:
return "Hold", reasons
else:
return "Sell", reasons
# Usage
analyzer = StockAnalyzer("PTT.BK")
print(analyzer.fundamental())
print(analyzer.technical())
rec, reasons = analyzer.recommendation()
print(f"Recommendation: {rec} ({', '.join(reasons)})")
"""
def show_code(self):
print("=== Stock Analyzer ===")
print(self.CODE[:600])
def demo_analysis(self):
print(f"\n=== Demo: หุ้นไทยยอดนิยม ===")
stocks = [
{"symbol": "PTT", "price": random.uniform(30, 40), "pe": random.uniform(8, 15), "rsi": random.randint(30, 70), "trend": "Uptrend"},
{"symbol": "ADVANC", "price": random.uniform(180, 220), "pe": random.uniform(18, 25), "rsi": random.randint(40, 65), "trend": "Sideways"},
{"symbol": "SCB", "price": random.uniform(90, 120), "pe": random.uniform(8, 12), "rsi": random.randint(35, 55), "trend": "Uptrend"},
{"symbol": "CPALL", "price": random.uniform(55, 70), "pe": random.uniform(20, 30), "rsi": random.randint(45, 70), "trend": "Uptrend"},
]
print(f" {'Symbol':<10} {'Price':>8} {'P/E':>6} {'RSI':>5} {'Trend':<10}")
for s in stocks:
print(f" {s['symbol']:<10} {s['price']:>8.2f} {s['pe']:>6.1f} {s['rsi']:>5} {s['trend']:<10}")
sa = StockAnalyzer()
sa.show_code()
sa.demo_analysis()
Chart Patterns
# patterns.py — Chart patterns for stock analysis
import json
class ChartPatterns:
REVERSAL = {
"head_shoulders": {
"name": "Head and Shoulders",
"type": "Bearish reversal",
"description": "ยอด 3 ยอด — ยอดกลางสูงสุด (head) ขนาบด้วย 2 ยอดเล็ก (shoulders)",
"signal": "ราคาหลุด neckline → ขาย",
"reliability": "สูงมาก (75-80%)",
},
"double_top": {
"name": "Double Top (M pattern)",
"type": "Bearish reversal",
"description": "ราคาขึ้นทดสอบแนวต้านเดิม 2 ครั้งแล้วหลุด",
"signal": "หลุด support → ขาย",
"reliability": "สูง (70-75%)",
},
"double_bottom": {
"name": "Double Bottom (W pattern)",
"type": "Bullish reversal",
"description": "ราคาลงทดสอบแนวรับเดิม 2 ครั้งแล้วเด้ง",
"signal": "breakout resistance → ซื้อ",
"reliability": "สูง (70-75%)",
},
}
CONTINUATION = {
"triangle": {
"name": "Triangle (Ascending, Descending, Symmetrical)",
"type": "Continuation",
"description": "ราคา consolidate ในรูปสามเหลี่ยม → breakout ตาม trend เดิม",
},
"flag": {
"name": "Flag & Pennant",
"type": "Continuation",
"description": "พัก consolidate สั้นๆ หลังจาก strong move → ไปต่อทิศทางเดิม",
},
"channel": {
"name": "Price Channel",
"type": "Trend following",
"description": "ราคาเคลื่อนที่ในกรอบขนาน — ซื้อที่ support, ขายที่ resistance",
},
}
def show_reversal(self):
print("=== Reversal Patterns ===\n")
for key, p in self.REVERSAL.items():
print(f"[{p['name']}] ({p['type']})")
print(f" {p['description']}")
print(f" Signal: {p['signal']}")
print()
def show_continuation(self):
print("=== Continuation Patterns ===")
for key, p in self.CONTINUATION.items():
print(f" [{p['name']}] {p['description']}")
patterns = ChartPatterns()
patterns.show_reversal()
patterns.show_continuation()
กลยุทธ์การลงทุน
# strategies.py — Investment strategies
import json
class InvestmentStrategies:
STRATEGIES = {
"value_investing": {
"name": "Value Investing (ลงทุนเน้นคุณค่า)",
"founder": "Benjamin Graham, Warren Buffett",
"method": "หาหุ้นที่ราคาต่ำกว่ามูลค่าแท้จริง (Margin of Safety)",
"criteria": "P/E ต่ำ, P/BV ต่ำ, ROE สูง, D/E ต่ำ, FCF เป็นบวก",
"timeframe": "ระยะยาว (3-10+ ปี)",
},
"growth_investing": {
"name": "Growth Investing (ลงทุนเน้นเติบโต)",
"founder": "Peter Lynch, Philip Fisher",
"method": "หาหุ้นที่กำไรเติบโตสูงกว่าตลาด",
"criteria": "EPS growth > 20%, Revenue growth สูง, P/E สูงได้ถ้า growth สูง",
"timeframe": "ระยะกลาง-ยาว (1-5 ปี)",
},
"momentum": {
"name": "Momentum Trading",
"method": "ซื้อหุ้นที่ราคากำลังขึ้น ขายหุ้นที่กำลังลง",
"criteria": "RSI trend, MACD crossover, Volume breakout",
"timeframe": "ระยะสั้น-กลาง (วัน - เดือน)",
},
"dividend": {
"name": "Dividend Investing (ลงทุนเพื่อปันผล)",
"method": "หาหุ้นที่จ่ายปันผลสม่ำเสมอ yield สูง",
"criteria": "Dividend Yield > 3%, Payout Ratio < 70%, จ่ายต่อเนื่อง 5+ ปี",
"timeframe": "ระยะยาว (ถือเก็บปันผล)",
},
}
def show_strategies(self):
print("=== Investment Strategies ===\n")
for key, strat in self.STRATEGIES.items():
print(f"[{strat['name']}]")
print(f" {strat['method']}")
print(f" เกณฑ์: {strat['criteria']}")
print(f" ระยะเวลา: {strat['timeframe']}")
print()
def beginner_recommendation(self):
print("=== แนะนำสำหรับมือใหม่ ===")
print(f" 1. เริ่มจาก Value + Dividend — ความเสี่ยงต่ำ, รายได้สม่ำเสมอ")
print(f" 2. เรียน Fundamental Analysis ก่อน — เข้าใจธุรกิจ")
print(f" 3. เสริมด้วย Technical Analysis — จับจังหวะซื้อ-ขาย")
print(f" 4. กระจายความเสี่ยง — ลงทุนหลาย sectors")
print(f" 5. ลงทุนสม่ำเสมอ (DCA) — ลดความเสี่ยงจาก timing")
strat = InvestmentStrategies()
strat.show_strategies()
strat.beginner_recommendation()
FAQ - คำถามที่พบบ่อย
Q: FA กับ TA ใช้อันไหนดีกว่า?
A: ใช้ทั้งคู่ดีที่สุด: FA บอกว่า "ซื้อหุ้นอะไร" (คุณค่าของธุรกิจ) TA บอกว่า "ซื้อเมื่อไหร่" (จังหวะราคา) มือใหม่: เริ่มจาก FA (เข้าใจธุรกิจ) → เสริม TA (จับจังหวะ) ระยะยาว: เน้น FA, ระยะสั้น: เน้น TA
Q: P/E เท่าไหร่ถือว่าถูก?
A: ไม่มีตัวเลขตายตัว — ต้องเทียบกับ industry average SET average: ~15-20x ธนาคาร: 8-12x, อาหาร: 15-25x, Tech: 20-40x P/E ต่ำ ≠ ถูกเสมอ — อาจเป็น value trap (บริษัทกำลังแย่ลง) ต้องดูร่วมกับ growth, ROE, D/E ด้วย
Q: RSI ใช้ยังไง?
A: RSI > 70: overbought — อาจปรับลง (แต่ใน strong trend อาจอยู่ > 70 นาน) RSI < 30: oversold — อาจดีดกลับ RSI Divergence: ราคาขึ้นแต่ RSI ลง = bearish signal อย่าใช้ RSI เดี่ยวๆ — ใช้ร่วมกับ trend, volume, support/resistance
Q: มือใหม่ควรเริ่มยังไง?
A: 1) เปิดบัญชีหุ้นกับโบรกเกอร์ (เลือกค่า commission ถูก) 2) เริ่มศึกษา FA — อ่านงบการเงิน, ดู P/E, ROE 3) เริ่มด้วย SET50 index fund (กระจายเสี่ยง) 4) ลงทุนทีละน้อย (DCA ทุกเดือน) 5) เรียนรู้ TA เพิ่มเติม — MA, RSI, MACD 6) อย่าลงทุนเงินที่ต้องใช้ในอนาคตอันใกล้
