03 พฤศจิกายน, 2026

ปรับปรุงโค้ดและเพิ่ม Trailing Stop

Sergey Eremin
RU TH

บทความนี้เป็นส่วนต่อเนื่องของซีรีส์ที่เริ่มต้นไว้ก่อนหน้านี้เกี่ยวกับการพัฒนา Expert Advisor (EA) (ดูฉบับที่ 61 และ 63 ของนิตยสาร ForTraders.org) น่าเสียดายที่งานด้านนี้ต้องหยุดชะงักไปหลายเดือน ทั้งสำหรับผมและผู้อ่านจำนวนมาก ด้วยเหตุผลหลายประการ แต่ที่สำคัญคือ ผมได้กลับมาสานต่องานนี้อีกครั้ง

สรุปผลจากการทดสอบที่ผ่านมา

ช่วงทดสอบสั้นๆ แสดงให้เห็นว่าแนวคิดนี้มีศักยภาพ แม้กำไรจะไม่สูง แต่สิ่งสำคัญกว่าคือไม่เกิดขาดทุน บทความนี้จะเสนอการปรับปรุงเพื่อเพิ่มประสิทธิภาพโปรแกรม โดยเริ่มจากชี้แจงจุดที่ไม่ชัดเจนในโค้ด และแก้ไขข้อผิดพลาดเล็กน้อย

ข้อผิดพลาดและจุดที่ไม่ชัดเจนในโค้ดของ EA

บรรทัดที่ 18 ของโค้ด:
Pause_Of_Trade_Try = 2; // ระยะเวลาพักระหว่างการพยายามเปิดออเดอร์ (หน่วย: วินาที)

ที่จริงแล้ว ค่าพารามิเตอร์นี้ไม่ได้ระบุเป็นวินาที แต่เป็น หนึ่งในสิบของวินาที ดังนั้นค่า 2 หมายถึง 0.2 วินาที

บรรทัดที่ 118–119 (และโค้ดลักษณะเดียวกันที่ปรากฏต่อไปในโปรแกรม):
return(OrderTicket());
break; // ออกจากลูป

อาจดูไม่ชัดเจนว่าทำไมจึงต้องใส่คำสั่ง break เนื่องจากเมื่อเรียก return แล้ว เราจะออกจากฟังก์ชันทันที ดังนั้นคำสั่ง break จึงไม่ถูกดำเนินการเลย นี่เป็นเพียงนิสัยส่วนตัวของผมที่มักใส่ break ทุกครั้งที่ต้องออกจากลูป อย่างไรก็ตาม ผมเคยพบภาษาโปรแกรมบางภาษาที่ลูปยังคงทำงานต่อไปหลังจาก return หากไม่มี break นอกจากนี้ นักเขียนโปรแกรมทุกคนทราบดีว่าในโครงสร้าง switch ของภาษา C จะเกิดกรณี “fall-through” (กระโดดไปยังคำสั่งถัดไปโดยอัตโนมัติ) หากไม่ใส่ break ดังนั้น การใส่ break ในที่นี้จึง ไม่จำเป็น

บรรทัดที่ 169 (และเนื้อหาของฟังก์ชัน sl):
double sl(int sl_value, int type, string symb=”NONE”, int rmode=1) {

อาจไม่ชัดเจนว่าพารามิเตอร์ rmode ใช้ทำอะไร และทำไมการคำนวณราคา Stop Loss (SL) จึงขึ้นกับค่านี้ โดยหาก rmode=1 จะคำนวณ SL ของออเดอร์ Buy จากราคา Ask และออเดอร์ Sell จากราคา Bid แต่ถ้า rmode=2 จะคำนวณ SL ของออเดอร์ Buy จากราคา Bid และออเดอร์ Sell จากราคา Ask (ดูเพิ่มเติมเรื่อง ราคา Bid)

ประเด็นนี้เป็นที่ถกเถียงกันว่า ควรคำนวณราคา Stop Loss จากราคาใด ฝ่ายหนึ่งเชื่อว่าเมื่อ触及 SL แล้ว ควรได้ขาดทุนตามจำนวนจุดที่ตั้งไว้พอดี (เช่น ตั้ง SL=100 ก็ขาดทุน 100 จุดพอดี) อีกฝ่ายเชื่อว่าควรรวมสเปรดเข้าไปด้วย เพื่อให้ตั้ง SL ได้ตามระยะที่ต้องการ โดยเฉพาะเมื่อสเปรดกว้างจนตั้ง SL ตามระยะที่ระบุไม่ได้ ซึ่งกรณีนี้ SL จะเท่ากับ 100 + <สเปรด> จุด

ผมส่วนใหญ่ใช้วิธีแรก และฟังก์ชันนี้ก็ออกแบบมาให้ทำงานตามวิธีนั้นเมื่อ rmode = 1 (ค่าเริ่มต้น) การเพิ่มพารามิเตอร์นี้แสดงให้เห็นว่าผมรับรู้ทั้งสองแนวทาง และไม่ได้บังคับให้ใช้วิธีใดวิธีหนึ่งโดยเฉพาะ (หากคุณสนับสนุนวิธีที่สอง ก็เพียงแค่เปลี่ยนค่า 1 เป็น 2 ในโค้ด) อย่างไรก็ตาม ผมเองใช้วิธีแรกในการเทรดจริง

ส่วนอื่น ๆ ของโค้ดดูมีตรรกะชัดเจนและเข้าใจง่าย แต่ในอนาคตผมอาจอธิบายเพิ่มเติมตามความจำเป็น

การปรับปรุงใหม่ใน EA

แม้จะได้ผลลัพธ์เบื้องต้นในช่วงเวลาสั้นๆ แต่ยังเร็วเกินไปที่จะกล่าวถึงการเปลี่ยนหรือปรับแต่งอัลกอริทึมค้นหาสัญญาณเทรด จึงขอเพิ่มฟังก์ชันใหม่สองรายการ ฟังก์ชันแรกคือ Trailing Stop ซึ่งผมจะนำฟังก์ชันมาตรฐานที่ใช้ใน EA อื่นๆ มาปรับเล็กน้อย เพื่อให้สามารถใช้งานพร้อมกันได้กับหลายคู่เงิน ฟังก์ชันนี้มีพารามิเตอร์เข้าดังนี้:

//+———————————————————————-+
//+ ฟังก์ชัน Trailing Stop +
extern bool UseTrailing = true; // เปิด/ปิดการใช้งาน T-SL
extern int TrailingStop = 50; // ระยะ Trailing Stop คงที่
extern int TrailingStep = 1; // ขั้นบันไดของ Trailing Stop
//+ ฟังก์ชัน Trailing Stop +
//+———————————————————————-+

โค้ดสำหรับทำงานกับคู่เงินปัจจุบันมีดังนี้:

//+——————————————————————————————————————-+
//| ฟังก์ชัน Trailing Stop Loss |
void T_SL() {
if(!UseTrailing) return;
int i = 0;
for(i=0; i<OrdersTotal(); i++) {
if(!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber()!=Magic_Number) continue;

if(OrderType()==OP_BUY) {
if(NormalizeDouble(Bid-OrderOpenPrice(),Digits)>NormalizeDouble(TrailingStop*Point,Digits)) {
if(NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(Bid-(TrailingStop+TrailingStep-1)*Point,Digits))
OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Bid-TrailingStop*Point,Digits), OrderTakeProfit(), 0, CLR_NONE);
} //end if(NormalizeDouble(Bid-OrderOpenPrice(),Digits)>NormalizeDouble(TrailingStop*Point,Digits))
} //end if(OrderType()==OP_BUY)

if(OrderType()==OP_SELL) {
if(NormalizeDouble(OrderOpenPrice()-Ask,Digits)>NormalizeDouble(TrailingStop*Point,Digits)) {
if(NormalizeDouble(OrderStopLoss(),Digits)>NormalizeDouble(Ask+(TrailingStop+TrailingStep-1)*Point,Digits))
OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Ask+TrailingStop*Point,Digits), OrderTakeProfit(), 0, CLR_NONE);
} //end if(NormalizeDouble(OrderOpenPrice()-Ask,Digits)>NormalizeDouble(TrailingStop*Point,Digits))
} //end if(OrderType()==OP_SELL)
} //end for(i=0; i<OrdersTotal(); i++)
} //end void T_SL()
//| ฟังก์ชัน Trailing Stop Loss |
//+——————————————————————————————————————-+

สำหรับ EA นี้ ต้องปรับโค้ดให้จัดการออเดอร์ทั้งหมด (ที่มี Magic Number ตรงกัน) ในทุกคู่เงินได้ ดังนี้:

//+——————————————————————————————————————-+
//| ฟังก์ชัน Trailing Stop Loss |
void T_SL() {
if(!UseTrailing) return;
string symb=””;
int i = 0;

double ask=0.0, bid=0.0, dig=0.0, pp=0.0;
for(i=0; i<OrdersTotal(); i++) {
if(!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue;
if(OrderMagicNumber()!=Magic_Number) continue;
symb=OrderSymbol();
pp=MarketInfo(symb,MODE_POINT);
dig=MarketInfo(symb,MODE_DIGITS);
ask=MarketInfo(symb,MODE_ASK);
bid=MarketInfo(symb,MODE_BID);
if(OrderType()==OP_BUY) {
if(NormalizeDouble(bid-OrderOpenPrice(),dig)>NormalizeDouble(TrailingStop*pp,dig)) {
if(NormalizeDouble(OrderStopLoss(),dig)<NormalizeDouble(bid-(TrailingStop+TrailingStep-1)*pp,dig))
OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(bid-TrailingStop*pp,dig), OrderTakeProfit(), 0, CLR_NONE);
} //end if(NormalizeDouble(Bid-OrderOpenPrice(),Digits)>NormalizeDouble(TrailingStop*Point,Digits))
} //end if(OrderType()==OP_BUY)

if(OrderType()==OP_SELL) {
if(NormalizeDouble(OrderOpenPrice()-ask,dig)>NormalizeDouble(TrailingStop*pp,dig)) {
if(NormalizeDouble(OrderStopLoss(),dig)>NormalizeDouble(ask+(TrailingStop+TrailingStep-1)*pp,dig))
OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(ask+TrailingStop*pp,dig), OrderTakeProfit(), 0, CLR_NONE);
} //end if(NormalizeDouble(OrderOpenPrice()-Ask,Digits)>NormalizeDouble(TrailingStop*Point,Digits))
} //end if(OrderType()==OP_SELL)
} //end for(i=0; i<OrdersTotal(); i++)
} //end void T_SL()
//| ฟังก์ชัน Trailing Stop Loss |
//+——————————————————————————————————————-+

จากนั้น เรียกใช้ฟังก์ชันนี้ภายในฟังก์ชัน start() (ดูในโค้ดฉบับสมบูรณ์)

ฟังก์ชันที่สองซึ่งมีประโยชน์และผมตัดสินใจเพิ่มลงใน EA คือ ส่งเสียงเตือนเมื่อเปิดออเดอร์ เนื่องจากเป็นส่วนเสริมขนาดเล็ก จึงไม่ขออธิบายรายละเอียด สามารถดูโค้ด EA ฉบับเต็มได้ที่ นี่

สรุป

ในเวอร์ชันถัดไปของ EA จะมีฟังก์ชันที่น่าสนใจมากขึ้น โดยมุ่งเน้นการควบคุมความเสี่ยงและการบริหารขนาดสถานะ (Position Sizing) สำหรับขณะนี้ ขอติดตามผลการทดสอบของเวอร์ชันนี้ก่อน

ติดตามเราทาง Telegram

Fortrader contentUrl Suite 11, Second Floor, Sound & Vision House, Francis Rachel Str. Victoria Victoria, Mahe, Seychelles +7 10 248 2640568

เพิ่มเติมจากหมวดหมู่นี้

บทความทั้งหมด

ออร์เดอร์ BuyStopLimit และ SellStopLimit

ออร์เดอร์ BuyStopLimit และ SellStopLimit คือฟีเจอร์ใหม่ใน MetaTrader 5 ที่สามารถจำลองการทำงานได้ใน MT4 ผ่านสคริปต์เฉพาะทาง

การดัดแปลงโปรแกรม MetaTrader4 ด้วยตนเอง (ตอนที่ 2)

บทความตอนที่ 2 ของซีรีส์การเขียนโปรแกรม MQL4 ที่อธิบายแนวคิดพื้นฐาน เช่น ตัวแปร ตัวดำเนินการ เงื่อนไข ลูป และฟังก์ชัน พร้อมแนวทางปฏิบัติสำหรับการดัดแปลงโปรแกรมด้วยตนเอง

ปรับแต่งโปรแกรม MetaTrader 4 ด้วยตนเอง (ตอนที่ 1)

เรียนรู้วิธีปรับแต่งโปรแกรมสำหรับ MetaTrader 4 ด้วยตนเอง: ตั้งแต่การหาซอร์สโค้ด วางไฟล์ให้ถูกต้อง ไปจนถึงเข้าใจโครงสร้างและอัลกอริทึมของ MQL4

Expert เทรดอัตโนมัติ “Forex Agent”

วิเคราะห์และปรับปรุง Expert Forex Agent v07 ให้กลายเป็น v08 โดยเปลี่ยนจังหวะการวาง Pending Order พร้อมผลลัพธ์ที่ดีขึ้นอย่างชัดเจน

บทความเพื่อการศึกษาล่าสุด

บทความทั้งหมด

บรรณาธิการแนะนำ

บทความทั้งหมด
เหตุใดธนาคารกลางอาจขึ้นอัตราดอกเบี้ย แต่ค่าเงินกลับลดลง
เริ่มต้นตลาดฟอเร็กซ์

เหตุใดธนาคารกลางอาจขึ้นอัตราดอกเบี้ย แต่ค่าเงินกลับลดลง

Vanessa Lourenco • 9 พ.ย., 2026
«Real Trading — 39»: การแข่งขันเทรดฟอเร็กซ์ 3 สัปดาห์ ชิงเงินรางวัลรวม $650
ข่าวประชาสัมพันธ์

«Real Trading — 39»: การแข่งขันเทรดฟอเร็กซ์ 3 สัปดาห์ ชิงเงินรางวัลรวม $650

ForTrader.org • 9 พ.ย., 2026
MiCA และสเทเบิลคอยน์: โทเค็นใดบ้างที่อาจหายไปจากกระดานซื้อขายคริปโตในยุโรป
ข้อมูลเชิงลึกคริปโต

MiCA และสเทเบิลคอยน์: โทเค็นใดบ้างที่อาจหายไปจากกระดานซื้อขายคริปโตในยุโรป

Kittisak Wongchai • 9 พ.ย., 2026
วิธีเลือกคู่สกุลเงินสำหรับการเทรดครั้งแรก
เริ่มต้นตลาดฟอเร็กซ์

วิธีเลือกคู่สกุลเงินสำหรับการเทรดครั้งแรก

Vanessa Lourenco • 9 พ.ย., 2026
กระแสเงินสดเสรี: ทำไมกำไรทางบัญชีอาจทำให้นักลงทุนเข้าใจผิด
พื้นฐานตลาดหุ้น

กระแสเงินสดเสรี: ทำไมกำไรทางบัญชีอาจทำให้นักลงทุนเข้าใจผิด

Marcel Tuinstra • 9 พ.ย., 2026
Octobank เริ่มเปิดรับชำระเงินผ่าน Apple Pay และ Google Pay สำหรับพันธมิตร
ข่าวประชาสัมพันธ์

Octobank เริ่มเปิดรับชำระเงินผ่าน Apple Pay และ Google Pay สำหรับพันธมิตร

ForTrader.org • 9 พ.ย., 2026