Trailing Stop ทำงานอย่างไร
Trailing Stop คือคำสั่งหยุดขาดทุน (Stop Loss) แบบเคลื่อนที่ตามราคา ใช้ในการเทรดหุ้น Forex Crypto และสินทรัพย์อื่นๆ เมื่อราคาเคลื่อนที่ไปในทิศทางที่เป็นประโยชน์ trailing stop จะปรับตัวตามอัตโนมัติ แต่เมื่อราคากลับตัว trailing stop จะหยุดนิ่งและ trigger เมื่อราคาถึง stop level ช่วยให้ lock กำไรได้โดยไม่ต้องเฝ้าหน้าจอตลอดเวลา เป็นเครื่องมือสำคัญสำหรับ risk management และ trend following strategies
หลักการทำงาน Trailing Stop
# trailing_stop.py — Trailing stop mechanics
import json
class TrailingStopMechanics:
TYPES = {
"fixed_distance": {
"name": "Fixed Distance Trailing Stop",
"description": "ห่างจากราคาปัจจุบันเป็นจำนวนคงที่ (เช่น 50 pips, 2%)",
"example": "ซื้อที่ 100 บาท, trailing 5 บาท → stop เริ่มที่ 95, ราคาขึ้น 110 → stop ขยับเป็น 105",
},
"percentage": {
"name": "Percentage Trailing Stop",
"description": "ห่างจากราคาสูงสุดเป็น % (เช่น 3%, 5%)",
"example": "ซื้อที่ 100, trail 5% → stop=95, ราคาขึ้น 120 → stop=114 (120×0.95)",
},
"atr_based": {
"name": "ATR-Based Trailing Stop",
"description": "ใช้ Average True Range กำหนดระยะห่าง (ปรับตาม volatility)",
"example": "ATR=2 บาท, multiplier=3 → trail distance=6 บาท (ปรับอัตโนมัติ)",
},
"moving_average": {
"name": "Moving Average Trailing Stop",
"description": "ใช้ MA เป็น trailing stop (เช่น EMA 20, SMA 50)",
"example": "ปิดสถานะเมื่อราคาหลุดต่ำกว่า EMA 20",
},
"chandelier": {
"name": "Chandelier Exit",
"description": "Trail จากจุดสูงสุด minus ATR × multiplier",
"example": "Highest High - (3 × ATR) = trailing stop level",
},
}
LONG_EXAMPLE = """
Trailing Stop (Long Position — ซื้อ):
ซื้อที่: 100 บาท | Trail: 5 บาท | Stop เริ่ม: 95 บาท
ราคา → Stop Action
100 95 เริ่มต้น
102 97 Stop ขยับขึ้น (+2)
105 100 Stop ขยับขึ้น (breakeven!)
110 105 Stop ขยับขึ้น (lock profit 5 บาท)
108 105 ราคาลง แต่ Stop ไม่ขยับลง
106 105 ราคาลงต่อ Stop ยังคงที่
105 105 ราคาถึง Stop → ปิดสถานะ! กำไร 5 บาท
"""
def show_types(self):
print("=== Trailing Stop Types ===\n")
for key, ts in self.TYPES.items():
print(f"[{ts['name']}]")
print(f" {ts['description']}")
print(f" Example: {ts['example']}")
print()
def show_example(self):
print("=== Long Position Example ===")
print(self.LONG_EXAMPLE)
ts = TrailingStopMechanics()
ts.show_types()
ts.show_example()
Python Implementation
# implementation.py — Trailing stop implementation
import json
import random
class TrailingStopBot:
def __init__(self, entry_price, trail_percent=5.0):
self.entry_price = entry_price
self.trail_percent = trail_percent
self.highest_price = entry_price
self.stop_price = entry_price * (1 - trail_percent / 100)
self.is_active = True
self.history = []
def update(self, current_price):
if not self.is_active:
return {"action": "CLOSED", "price": current_price}
if current_price > self.highest_price:
self.highest_price = current_price
self.stop_price = self.highest_price * (1 - self.trail_percent / 100)
triggered = current_price <= self.stop_price
if triggered:
self.is_active = False
result = {
"price": current_price,
"highest": self.highest_price,
"stop": round(self.stop_price, 2),
"pnl": round(current_price - self.entry_price, 2),
"pnl_pct": round((current_price - self.entry_price) / self.entry_price * 100, 2),
"action": "STOP TRIGGERED" if triggered else "HOLD",
}
self.history.append(result)
return result
def simulate(self, prices):
print(f"=== Trailing Stop Simulation ===")
print(f"Entry: {self.entry_price} | Trail: {self.trail_percent}%\n")
print(f"{'Price':>8} {'Highest':>8} {'Stop':>8} {'P&L':>8} {'Action'}")
print(f"{'-'*50}")
for price in prices:
r = self.update(price)
print(f"{r['price']:>8.2f} {r['highest']:>8.2f} {r['stop']:>8.2f} {r['pnl']:>+8.2f} {r['action']}")
if r["action"] == "STOP TRIGGERED":
break
# Simulate
prices = [100, 102, 105, 108, 112, 110, 115, 118, 116, 113, 112]
bot = TrailingStopBot(entry_price=100, trail_percent=5)
bot.simulate(prices)
ATR Trailing Stop
# atr_trail.py — ATR-based trailing stop
import json
import random
class ATRTrailingStop:
def calculate_atr(self, highs, lows, closes, period=14):
trs = []
for i in range(1, len(highs)):
tr = max(
highs[i] - lows[i],
abs(highs[i] - closes[i-1]),
abs(lows[i] - closes[i-1])
)
trs.append(tr)
if len(trs) < period:
return sum(trs) / len(trs) if trs else 0
atr = sum(trs[:period]) / period
for i in range(period, len(trs)):
atr = (atr * (period - 1) + trs[i]) / period
return round(atr, 4)
def atr_trailing(self, closes, atr_value, multiplier=3):
trail_distance = atr_value * multiplier
highest = closes[0]
stop = closes[0] - trail_distance
print(f"=== ATR Trailing Stop ===")
print(f"ATR: {atr_value:.2f} | Multiplier: {multiplier} | Distance: {trail_distance:.2f}\n")
for price in closes:
if price > highest:
highest = price
stop = highest - trail_distance
triggered = price <= stop
action = "STOP!" if triggered else "HOLD"
print(f" Price={price:>8.2f} Stop={stop:>8.2f} {action}")
if triggered:
break
def demo(self):
closes = [100 + random.uniform(-2, 3) for _ in range(20)]
for i in range(1, len(closes)):
closes[i] = closes[i-1] + random.uniform(-1.5, 2.0)
atr = self.calculate_atr(
[c + random.uniform(0, 2) for c in closes],
[c - random.uniform(0, 2) for c in closes],
closes, period=14
)
self.atr_trailing(closes[:15], atr, multiplier=3)
atr = ATRTrailingStop()
atr.demo()
Platform-Specific Setup
# platforms.py — Trailing stop on different platforms
import json
class PlatformSetup:
PLATFORMS = {
"mt4_mt5": {
"name": "MetaTrader 4/5 (Forex)",
"setup": "Order → Trailing Stop → กำหนด pips (เช่น 50 pips)",
"note": "ต้องเปิด MT4/MT5 ไว้ตลอด (trail ทำงานบน client)",
"mql5_code": """
// MQL5 Trailing Stop EA
void OnTick() {
for(int i = PositionsTotal()-1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)) {
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
double sl = PositionGetDouble(POSITION_SL);
double trailPoints = 500; // 50 pips
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
double newSL = currentPrice - trailPoints * _Point;
if(newSL > sl && newSL > openPrice) {
trade.PositionModify(ticket, newSL, 0);
}
}
}
}
}
""",
},
"binance": {
"name": "Binance (Crypto)",
"setup": "Spot → Trailing Stop Order → Callback Rate 1-5%",
"note": "Server-side trailing (ไม่ต้องเปิด app)",
},
"set_thai": {
"name": "SET (หุ้นไทย)",
"setup": "โบรกเกอร์บางเจ้ารองรับ trailing stop (Settrade, Streaming)",
"note": "ถ้าไม่รองรับ: ใช้ alert + manual stop",
},
}
def show_platforms(self):
print("=== Platform Setup ===\n")
for key, platform in self.PLATFORMS.items():
print(f"[{platform['name']}]")
print(f" Setup: {platform['setup']}")
print(f" Note: {platform['note']}")
print()
def show_mql5(self):
print("=== MQL5 Code ===")
print(self.PLATFORMS["mt4_mt5"]["mql5_code"][:400])
platforms = PlatformSetup()
platforms.show_platforms()
platforms.show_mql5()
Strategy & Best Practices
# strategy.py — Trailing stop strategies
import json
import random
class TrailingStrategy:
STRATEGIES = {
"trend_following": {
"name": "Trend Following",
"trail": "ATR × 2-3 หรือ 5-10%",
"best_for": "ตลาด trending, swing trading",
"risk": "ถูก stop ออกเร็วถ้า trail แคบเกินไป",
},
"breakout": {
"name": "Breakout Trading",
"trail": "เริ่ม trail หลังราคาเคลื่อนที่ 1-2 ATR จากจุด entry",
"best_for": "เทรด breakout จาก support/resistance",
"risk": "False breakout → stop triggered เร็ว",
},
"position_trading": {
"name": "Position Trading (ระยะยาว)",
"trail": "MA 50 หรือ 10-20% จาก highest",
"best_for": "ถือหุ้นระยะยาว, ลงทุน crypto",
"risk": "Trail กว้าง = drawdown มาก",
},
"scalping": {
"name": "Scalping (ระยะสั้นมาก)",
"trail": "1-2% หรือ ATR × 1",
"best_for": "เทรดสั้น 1-15 นาที",
"risk": "ถูก stop บ่อย (noise ของตลาด)",
},
}
MISTAKES = [
"Trail แคบเกินไป → ถูก stop ออกจาก noise ทุกครั้ง",
"Trail กว้างเกินไป → คืนกำไรเกือบหมดก่อน stop trigger",
"ไม่ปรับ trail ตาม volatility → ใช้ค่าเดิมทุกสถานการณ์",
"ใช้ trailing stop ใน sideways market → ถูก whipsaw",
"ขยับ stop ลง (ถอย) → ผิดหลัก money management",
]
def show_strategies(self):
print("=== Trailing Stop Strategies ===\n")
for key, strategy in self.STRATEGIES.items():
print(f"[{strategy['name']}]")
print(f" Trail: {strategy['trail']}")
print(f" Best for: {strategy['best_for']}")
print()
def show_mistakes(self):
print("=== Common Mistakes ===")
for mistake in self.MISTAKES[:4]:
print(f" ✗ {mistake}")
def backtest(self):
print(f"\n=== Backtest Results (100 trades) ===")
trails = {"3%": None, "5%": None, "10%": None, "ATR×2": None}
for trail in trails:
win_rate = random.randint(35, 55)
avg_win = random.uniform(5, 15)
avg_loss = random.uniform(2, 6)
expectancy = (win_rate/100 * avg_win) - ((100-win_rate)/100 * avg_loss)
print(f" [{trail:>5}] Win: {win_rate}% | Avg W: +{avg_win:.1f}% | Avg L: -{avg_loss:.1f}% | E: {expectancy:+.2f}%")
strat = TrailingStrategy()
strat.show_strategies()
strat.show_mistakes()
strat.backtest()
FAQ - คำถามที่พบบ่อย
Q: Trailing Stop กับ Stop Loss ต่างกันอย่างไร?
A: Stop Loss: คงที่ ไม่ขยับ (เช่น stop ที่ 95 ตลอด) Trailing Stop: ขยับตามราคา (ถ้าราคาขึ้น stop ขยับขึ้นตาม) Stop Loss ป้องกันขาดทุน Trailing Stop ป้องกันขาดทุน + lock กำไร ใช้ร่วมกัน: เริ่มด้วย Stop Loss → เปลี่ยนเป็น Trailing Stop เมื่อมีกำไร
Q: Trailing Stop กี่ % ดี?
A: ขึ้นอยู่กับ: สินทรัพย์, timeframe, volatility หุ้นไทย: 5-10% Forex: 1-3% (หรือ 30-100 pips) Crypto: 5-15% (volatile สูง) กฎทั่วไป: ใช้ 2-3 × ATR หรือ backtest หา optimal %
Q: ใช้ Trailing Stop ใน sideways market ได้ไหม?
A: ไม่แนะนำ Sideways = ราคาแกว่ง → trailing stop ถูก trigger บ่อย (whipsaw) ดีกว่า: ใช้ fixed take profit + stop loss ใน sideways ใช้ trailing stop เฉพาะใน trending market ตรวจ trend ก่อน: ADX > 25 = trending, ADX < 20 = sideways
Q: Server-side กับ Client-side trailing stop ต่างกันอย่างไร?
A: Server-side (Binance, broker): ทำงานบน server ไม่ต้องเปิด app Client-side (MT4/MT5): ทำงานบนเครื่องเรา ต้องเปิด platform ไว้ ถ้าปิด MT4 = trailing stop หยุดทำงาน แก้: ใช้ VPS สำหรับ MT4/MT5 หรือเลือก broker ที่มี server-side trailing
