OrderSend() ใน MQL4 คืออะไร — พารามิเตอร์ทั้ง 11 ตัว ค่าที่คืนกลับมา และตาราง error ที่เจอบ่อยที่สุด
OrderSend() คือฟังก์ชันเดียวใน MQL4 ที่ส่งคำสั่งเปิดออเดอร์ออกไปจริง ๆ — ถ้าสำเร็จมันคืนค่าเป็น เลขตั๋ว (ticket) ที่เป็นจำนวนเต็มบวก ถ้าไม่สำเร็จมันคืน −1 แล้วเก็บสาเหตุไว้ให้ไปอ่านด้วย GetLastError() · หน้านี้สรุปพารามิเตอร์ทั้ง 11 ตัว · ตารางแปล error ที่เจอบ่อยที่สุด · และรูปแบบการเขียนที่ต้องเลี่ยงที่สุด
OrderSend() คืนกลับมา — เลขตั๋วของออเดอร์ที่เปิดสำเร็จ · ถ้าตรงนี้เป็น −1 แปลว่าคำสั่งไม่ได้ออกไปเลย และต้องไปอ่านว่าติดที่ error ตัวไหนบทความหลักมีโค้ดฟังก์ชันเปิดออเดอร์เต็ม ๆ ที่นับไม้ก่อนยิงและไม่วนส่งซ้ำ · พร้อมโครงไฟล์และตารางเรื่อง Bid/Ask
OrderSend() รับค่าอะไรบ้าง — พารามิเตอร์ทั้ง 11 ตัว
ลำดับของพารามิเตอร์ห้ามสลับ และสามตัวท้ายมีค่าเริ่มต้นให้อยู่แล้วจึงเว้นไม่ใส่ได้
int OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color)
| # | พารามิเตอร์ | ชนิด | ใส่อะไร และจุดที่พลาดบ่อย |
|---|---|---|---|
| 1 | symbol | string | ชื่อคู่เงิน ⇒ ใช้ Symbol() เพื่อเอาคู่ของชาร์ตที่ EA เกาะอยู่ · อย่าพิมพ์ชื่อตายตัว เพราะโบรกหลายเจ้ามีคำต่อท้ายอย่าง GBPUSDm หรือ GBPUSD.pro |
| 2 | cmd | int | ชนิดคำสั่ง — OP_BUY · OP_SELL · OP_BUYLIMIT · OP_SELLLIMIT · OP_BUYSTOP · OP_SELLSTOP |
| 3 | volume | double | ขนาดล็อต ⇒ ต้องเป็นพหุคูณของ MODE_LOTSTEP ไม่งั้นได้ error 131 (ดูตารางข้างล่าง) |
| 4 | price | double | ราคาที่จะส่ง — BUY ใช้ Ask · SELL ใช้ Bid ⇒ สลับข้างเมื่อไรได้ error 129 หรือเข้าที่ราคาผิดทันที |
| 5 | slippage | int | เพดานความคลาดของราคา นับเป็นจุด (point) ไม่ใช่ pip ⇒ บัญชี 5 หลัก ใส่ 3 = ยอมคลาดแค่ 0.3 pip เท่านั้น |
| 6 | stoploss | double | ราคาจุดตัดขาดทุน · ใส่ 0 คือไม่ตั้ง ⇒ ต้องห่างจากราคาอย่างน้อย MODE_STOPLEVEL ไม่งั้นได้ error 130 |
| 7 | takeprofit | double | ราคาจุดทำกำไร · ใส่ 0 คือไม่ตั้ง ⇒ เงื่อนไขระยะห่างเหมือน stoploss ทุกประการ |
| 8 | comment | string | ข้อความติดไม้ · ไม่ใช่ที่สำหรับระบุตัว EA เพราะโบรกเขียนทับได้ ⇒ ใช้ magic แทน |
| 9 | magic | int | เลขประจำตัว EA ⇒ ตัวเดียวที่ใช้แยกไม้ของ EA ตัวนี้ออกจากไม้อื่นได้จริง |
| 10 | expiration | datetime | เวลาหมดอายุของ pending order · ใช้กับ OP_BUY / OP_SELL ไม่ได้ ⇒ ใส่ไปกับไม้ market จะได้ error 147 |
| 11 | arrow_color | color | สีลูกศรบนชาร์ต · clrNONE คือไม่วาด ⇒ ไม่มีผลกับการเทรดเลย |
ค่าที่คืนกลับมา และวิธีอ่าน error ให้เห็นสาเหตุ
- สำเร็จ ⇒ คืนเลขตั๋ว เป็นจำนวนเต็มบวก (เลข 349 ในภาพด้านบน) ⇒ เก็บไว้ใช้อ้างอิงตอนแก้หรือปิดไม้นั้น
- ไม่สำเร็จ ⇒ คืน
-1⇒ ต้องเรียกGetLastError()ทันทีบรรทัดถัดไป เพราะค่านี้ถูกล้างเมื่อมีการเรียกฟังก์ชันอื่นคั่น - พิมพ์ออกมาด้วย
Print()เสมอ ⇒ ข้อความจะไปโผล่ที่แท็บ Experts ส่วนคำสั่งที่โบรกปฏิเสธจะขึ้นที่แท็บ Journal - ตรวจค่าที่คืนมาทุกครั้ง ⇒ โค้ดที่เขียน
OrderSend(...)ลอย ๆ โดยไม่รับค่ากลับ คือโค้ดที่ไม่มีวันรู้ว่าคำสั่งออกไปหรือไม่
OrderOpenPrice() หลัง OrderSelect() ⇒ ส่วนต่างระหว่างสองค่านี้คือสิ่งที่ slippage คุมอยู่ ดูว่ามันกินแผนไปเท่าไรที่ Requote คืออะไรตาราง error ของ OrderSend ที่เจอบ่อยที่สุด
ตัวเลขพวกนี้คือค่าที่ GetLastError() คืนกลับมา · เรียงตามที่เจอบ่อยในงานจริง
| รหัส | ค่าคงที่ | แปลว่า | สาเหตุที่เจอจริง และทางแก้ |
|---|---|---|---|
| 130 | ERR_INVALID_STOPS | SL / TP ไม่ถูกต้อง | ตั้งใกล้ราคาเกิน MODE_STOPLEVEL · ตั้งผิดฝั่ง · หรือทศนิยมไม่ตรง Digits ⇒ ครอบด้วย NormalizeDouble(..., Digits) ทุกครั้ง และเช็กระยะก่อนส่ง |
| 131 | ERR_INVALID_TRADE_VOLUME | ขนาดล็อตไม่ถูกต้อง | ล็อตที่คำนวณได้ไม่ลงตัวกับ MODE_LOTSTEP หรือต่ำกว่า MODE_MINLOT ⇒ ปัดให้ลงตัวก่อนส่ง (ดูตารางข้างล่าง) |
| 134 | ERR_NOT_ENOUGH_MONEY | เงินไม่พอวางมาร์จิ้น | ล็อตใหญ่เกินทุนที่เหลือ · มักเกิดหลังแพ้ติดกันหลายไม้จนทุนลด ⇒ คำนวณล็อตจากทุนปัจจุบัน ไม่ใช่ทุนตั้งต้น |
| 138 | ERR_REQUOTE | ราคาเปลี่ยนก่อนคำสั่งถึง | ปกติในข่าวแรง ⇒ ปล่อยผ่านไปรอบหน้า อย่ายิงซ้ำในวินาทีเดียวกัน (เหตุผลอยู่ในหัวข้อถัดไป) |
| 136 | ERR_OFF_QUOTES | โบรกไม่มีราคาให้ | ตลาดบางมาก หรือคู่เงินนั้นหยุดซื้อขายชั่วคราว ⇒ รอรอบถัดไป ไม่ใช่เร่งยิง |
| 132 | ERR_MARKET_CLOSED | ตลาดปิด | เจอบ่อยตอนทดสอบสุดสัปดาห์ ⇒ ไม่ใช่บั๊กของโค้ด |
| 146 | ERR_TRADE_CONTEXT_BUSY | ช่องส่งคำสั่งไม่ว่าง | มี EA หลายตัวยิงพร้อมกันบนเทอร์มินัลเดียว ⇒ เช็ก IsTradeContextBusy() ก่อนส่ง |
| 148 | ERR_TRADE_TOO_MANY_ORDERS | ไม้เปิดพร้อมกันเกินเพดาน | ชนเพดานของโบรก ⇒ เป็นสัญญาณว่าโค้ดกำลังเปิดซ้ำ ไม่ใช่ปัญหาของโบรก |
| 4109 | ERR_TRADE_NOT_ALLOWED | ไม่อนุญาตให้เทรด | ไม่ได้ติ๊ก Allow live trading ⇒ แก้ที่หน้าต่างตั้งค่า EA ไม่ใช่ที่โค้ด |
| 4107 | ERR_INVALID_PRICE_PARAM | ค่าราคาที่ส่งใช้ไม่ได้ | ส่งราคาเป็น 0 หรือค่าที่คำนวณพลาดจนติดลบ ⇒ พิมพ์ค่าที่จะส่งออกมาดูก่อนยิง |
| 4051 | ERR_INVALID_FUNCTION_PARAMVALUE | ค่าพารามิเตอร์ใช้ไม่ได้ | มักเป็นล็อตหรือ cmd ที่เป็นค่าว่าง ⇒ ตรวจว่าตัวแปรถูกกำหนดค่าแล้วจริง |
| 2 / 3 | ERR_COMMON_ERROR · ERR_INVALID_TRADE_PARAMETERS | ผิดพลาดทั่วไป | ตัวจับฉลากของ MT4 ⇒ เริ่มจากพิมพ์ทุกค่าที่กำลังจะส่งออกมาดูทีละตัว |
ทำไม error 130 ถึงเป็นตัวที่เจอบ่อยที่สุด
เพราะโบรกแต่ละเจ้าตั้ง MODE_STOPLEVEL ไม่เท่ากัน โค้ดชุดเดียวจึงผ่านที่โบรกหนึ่งและไม่ผ่านที่อีกโบรกหนึ่ง สมมติ GBPUSD บัญชี 5 หลัก Bid = 1.60085 · เปิด BUY แล้วตั้ง SL ห่างจาก Bid ลงมา 20 จุด (= 1.60065)
| MODE_STOPLEVEL ของโบรก | ระยะขั้นต่ำที่ยอม | SL สูงสุดที่ตั้งได้ | ส่ง SL = 1.60065 |
|---|---|---|---|
| 0 จุด | ไม่จำกัด | 1.60085 | ✅ ผ่าน |
| 10 จุด | 1.0 pip | 1.60075 | ✅ ผ่าน |
| 20 จุด | 2.0 pip | 1.60065 | ✅ ผ่านพอดีเส้น |
| 30 จุด | 3.0 pip | 1.60055 | 🔴 error 130 |
| 50 จุด | 5.0 pip | 1.60035 | 🔴 error 130 |
สังเกตว่า โค้ดไม่ได้เปลี่ยนเลยสักบรรทัด เปลี่ยนแค่โบรก ⇒ อย่าฝังระยะ SL เป็นตัวเลขตายตัวในโค้ด ให้อ่าน MarketInfo(Symbol(), MODE_STOPLEVEL) มาเทียบก่อนส่งทุกครั้ง
error 131 มาจากการปัดล็อต ไม่ใช่จากล็อตใหญ่เกิน
สูตรคำนวณล็อตจากเปอร์เซ็นต์ความเสี่ยงแทบไม่เคยให้เลขที่ลงตัวพอดี ตัวอย่างจริง — เสี่ยง 1% ต่อไม้ · SL 23 pip · GBPUSD ที่ 1.00 ล็อตมีค่าประมาณ 10 ดอลลาร์ต่อ pip
| ทุน | เสี่ยง 1% เป็นเงิน | ล็อตที่สูตรให้ | MODE_LOTSTEP 0.01 | ผลที่ตามมา |
|---|---|---|---|---|
| 3,000 | 30.00 | 0.1304347… | ส่งตรง ๆ = 🔴 131 · ต้องปัดเป็น 0.13 | เสี่ยงจริง 29.90 ≈ ตามแผน |
| 1,000 | 10.00 | 0.0434782… | ต้องปัดเป็น 0.04 | เสี่ยงจริง 9.20 — ต่ำกว่าแผนเล็กน้อย |
| 100 | 1.00 | 0.0043478… | 🔴 ต่ำกว่า MODE_MINLOT 0.01 | ถูกบังคับใช้ 0.01 ⇒ เสี่ยงจริง 2.30 = 2.3% ของทุน หรือ 2.3 เท่าของแผน |
ทำไมลูปส่งซ้ำถึงอันตราย
ตรรกะที่ดูสมเหตุสมผลคือ "ถ้าส่งไม่สำเร็จก็ส่งใหม่จนกว่าจะได้" — ปัญหาคือคำสั่งที่ตอบกลับช้าไม่ได้แปลว่าล้มเหลว ในช่วงที่ตลาดผันผวน คำสั่งแรกอาจสำเร็จไปแล้วแต่ผลตอบกลับยังไม่มาถึง โค้ดจึงส่งใหม่ทับเข้าไป
| เขียนลูปให้ส่งซ้ำได้ | กรณีแย่สุดเปิดได้กี่ไม้ | ความเสี่ยงเทียบกับแผน |
|---|---|---|
| ไม่วนซ้ำเลย (ยิงครั้งเดียว) | 1 ไม้ | 1 เท่า — ตรงตามแผน |
| วนได้ 3 ครั้ง | 3 ไม้ | 3 เท่า |
| วนได้ 5 ครั้ง | 5 ไม้ | 5 เท่า |
| ไม่จำกัดจำนวนครั้ง | 🔴 ยิงไม่หยุดจนกว่าเงื่อนไขจะเปลี่ยน — เป็นรูปแบบที่ล้างพอร์ตได้เร็วที่สุด | |
สังเกตความเชื่อมโยง: error 148 (ไม้เกินเพดาน) เกือบทุกครั้งเป็นผลลัพธ์ปลายทางของลูปส่งซ้ำ ไม่ใช่ปัญหาที่ต้องไปขอโบรกขยายเพดาน · ส่วนตัวคุมไม่ให้เปิดซ้ำภายในแท่งเดียวกันมีโค้ดอยู่ที่ EA เปิดออร์เดอร์ซ้ำในแท่งเดียว
สิ่งที่ต้องมีในฟังก์ชันเปิดออเดอร์
- Magic Number — เลขประจำตัว EA ⇒ ถ้าไม่มี
OrdersTotal()จะนับไม้ของทุกคนบนบัญชีนั้นรวมกัน และ EA สองตัวจะปิดไม้ของกันและกัน - นับไม้ของตัวเองก่อนยิง — วนดูออเดอร์ที่เปิดอยู่ กรองด้วย
OrderSymbol()และOrderMagicNumber()⇒ มีอยู่แล้วก็ไม่เปิดซ้ำ - เลือกราคาให้ถูกฝั่ง — BUY ส่งที่
Ask· SELL ส่งที่Bid⇒ ดูรายละเอียดที่ Bid กับ Ask ก่อนเขียน EA - ครอบทุกราคาด้วย
NormalizeDouble— ทั้งprice·stoploss·takeprofit⇒ ตัวนี้ตัดสาเหตุของ error 130 ออกไปได้หนึ่งข้อทันที - ตั้งเพดานความคลาดของราคา —
slippageนับเป็นจุด ไม่ใช่ pip ⇒ อ่านตัวเลขว่ามันกินแผนไปเท่าไรที่ Requote คืออะไร - อ่านค่า error เมื่อไม่สำเร็จ —
GetLastError()แล้วPrint()ออกมา ⇒ ไม่งั้นจะไม่มีทางรู้ว่าทำไมไม่เข้า
อ่านต่อในบทความหลัก
- โค้ดฟังก์ชันเปิดออเดอร์เต็ม ๆ — มี
CountMyOrders()ที่กรองด้วย Magic Number และไม่วนส่งซ้ำ - โครงไฟล์ EA ที่ก็อปไปใช้ได้เลย — พร้อมตัวคุมให้ทำงานแท่งละครั้ง
- Bid กับ Ask — ตารางที่บอกว่าตั้ง TP ผิดข้างแล้วออกช้าไป 6 จุด
- ก่อนปล่อยลงบัญชีจริง — ลำดับทดสอบสามชั้นและคำถามที่แต่ละชั้นตอบได้จริง
→ อ่านฉบับเต็ม: เริ่มต้นเขียน EA (MQL4)
บทความนี้เป็นเนื้อหาให้ความรู้ด้านการเขียนโปรแกรมเท่านั้น ไม่ใช่คำแนะนำการลงทุน · ค่า MODE_STOPLEVEL · MODE_MINLOT · MODE_LOTSTEP และรายการ error ที่โบรกคืนกลับมาต่างกันไปในแต่ละโบรกและแต่ละบัญชี ⇒ ให้อ่านค่าจริงจากเทอร์มินัลของตัวเองเสมอ ตัวเลขในตารางเป็นตัวอย่างการคำนวณ · โค้ดตัวอย่างควรทดสอบบนบัญชีทดลองก่อนเสมอ การเทรดมีความเสี่ยงที่จะสูญเสียเงินลงทุน ผู้อ่านควรศึกษาและตัดสินใจด้วยตนเอง
ความคิดเห็น
แสดงความคิดเห็น