วันนี้เรามาพูดคุยเกี่ยวกับอินดิเคเตอร์ที่ช่วยให้คุณสามารถแสดงแนวโน้มปัจจุบันในทุกช่วงเวลาได้ในพาแนลเดียวกัน ซึ่งเป็นเครื่องมือที่ดีสำหรับนักเทรดที่ต้องการมองเห็นภาพรวมของตลาดอย่างรวดเร็ว
อินดิเคเตอร์นี้เป็นกราฟฟิกที่อิงจาก Slope-Direction-Trend Indicator ที่มีการเผยแพร่ในรูปแบบต่าง ๆ มาแล้วมากมาย แต่ไม่มีรุ่นไหนที่สามารถแสดงทุกช่วงเวลาในพาแนลกราฟฟิกเดียวกันบนหน้าจอของคุณ
คุณสามารถค้นหาได้ที่ https://www.mql5.com/en/search#!keyword=slope%20direction%20line เพื่อดูผลลัพธ์ต่าง ๆ
ผมได้ทำการดัดแปลงอินดิเคเตอร์นี้ให้สามารถแสดงผลในพาแนลกราฟฟิกที่แสดงทุกช่วงเวลา และได้ทำการปรับเปลี่ยนโค้ดต้นฉบับเล็กน้อย หนึ่งในฟีเจอร์ที่เพิ่มเข้ามาคือการให้ผู้ใช้เลือกวิธีการคำนวณค่าเฉลี่ยเคลื่อนที่ที่สองสำหรับการปรับเรียบ โค้ดต้นฉบับใช้ Linear Weighted สำหรับการประมวลผลครั้งที่สอง แต่ผมได้ให้ผู้ใช้เลือกวิธีการปรับเรียบตามที่ต้องการ เมื่อใช้ Linear Weighted สำหรับการคำนวณทั้งสองครั้ง มันอาจทำให้การอ่านค่าแนวโน้มปัจจุบันไม่แม่นยำ แต่ถ้าเราใช้ Simple เป็นวิธีการเฉลี่ยที่สอง เราจะได้แนวโน้มที่แสดงถึงทิศทางราคาที่ถูกต้องมากขึ้น
อีกหนึ่งการเปลี่ยนแปลงที่ผมได้ทำคือ การไม่เพียงแค่แสดงทิศทางของแนวโน้ม (ขึ้น, ลง หรือ แฟลต) แต่ยังสามารถแสดงค่าของมันได้ด้วย สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการใช้ Double SlopeDirection Indicator และการสร้าง Expert Advisor ด้วยมัน ผมจะเขียนในบทความถัดไป

มาดูโค้ดกันเลยนะครับ ผมจะเริ่มต้นด้วยการกำหนดชื่อวัตถุทั้งหมดที่ผมจะใช้ การทำเช่นนี้เป็นการปฏิบัติที่ดีเพราะแต่ละครั้งที่เรากำหนดชื่อวัตถุในเครื่องหมายคำพูด มันจะใช้พื้นที่ในโปรแกรม ดังนั้นถ้ามันถูกกำหนดเพียงครั้งเดียว (โดยใช้คำสั่ง define) คุณจะใช้พื้นที่ในโค้ดแค่ครั้งเดียว
// กำหนดทิศทางแนวโน้ม #define UPTREND 1 #define DOWNTREND -1 #define FLATTREND 0 // กำหนดวัตถุ #define TrendPanel "TrendPanel" #define InfoLine1 "InfoLine1" #define InfoLine2 "InfoLine2" #define TrendLabel "แนวโน้ม: M1 M5 M15 M30 H1 H4 D1 W1 MN" #define TrendUp "\233" #define TrendDown "\234" #define TrendFlat "\232" #define TrendUnknown "\251" #define StatObjectError "%s(%d) สร้าง '%s' ไม่สำเร็จ. Error = %d"
ถัดไปผมจะกำหนดอาร์เรย์สองตัว หนึ่งสำหรับตำแหน่งพิกเซลสำหรับช่วงเวลาทั้ง 9 และอีกตัวสำหรับช่วงเวลา ซึ่งถูกกำหนดเป็นตัวแปรทั่วโลก
// กำหนดตัวแปรทั่วโลก int TrendPosition[] = { 44, 64, 88, 114, 136, 156, 174, 194, 216 }; int TrendPeriods[] = { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1 };
ฟังก์ชั่น OnInit() ของเราจะเรียกฟังก์ชั่นเพื่อสร้างพาแนลและวัตถุภายในพาแนล นอกจากนี้ยังทำการตรวจสอบ "Dumn Dumn" เร็ว ๆ ที่บาร์ที่ใช้ในการคำนวณแนวโน้ม หากน้อยกว่า 3 ก็แทบจะไร้ประโยชน์
//+------------------------------------------------------------------+ //| ฟังก์ชั่นเริ่มต้นของอินดิเคเตอร์ | //+------------------------------------------------------------------+ int OnInit() { // ไปสร้างวัตถุสำหรับพาแนลอินดิเคเตอร์ if(Create_Panel() && BarCount >= 3) return(INIT_SUCCEEDED); else return(INIT_FAILED); }
ผมจะไม่ลงรายละเอียดเกี่ยวกับการทำงานของฟังก์ชั่น GetTrend() จะมีเอกสารดี ๆ อยู่แล้วที่นี่สำหรับเรื่องนั้น เรามาดูฟังก์ชั่น DisplayTrend() ที่แสดงกราฟิกกันดีกว่า
//+------------------------------------------------------------------+ //| แสดงแนวโน้มปัจจุบันสำหรับทุกช่วงเวลา //+------------------------------------------------------------------+ void DisplayTrend(void) { int i, cntr, Trend, LastTrend; string str; for(i=1; i<10; i++) { str = "Trend" + DoubleToStr(i, 0); Trend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method); if(Trend == FLATTREND) { // แฟลต, หาแนวโน้มสุดท้าย cntr = 1; do { LastTrend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method, false, cntr++); } while(LastTrend == Trend); ObjectSetText(str, TrendFlat, 8, "WingDings", (LastTrend == UPTREND ? Green : Red)); ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 6); } else { ObjectSetText(str, (Trend == UPTREND ? TrendUp : TrendDown), 8, "WingDings", (Trend == UPTREND ? Green : Red)); ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 5 + (Trend == UPTREND ? 1 : -1)); } } }
เราจะวนลูปผ่านอาร์เรย์ TrendPeriods[] (เพื่อให้ได้ทุกช่วงเวลา) และตั้งค่าสัญลักษณ์แนวโน้มตามทิศทางแนวโน้มของช่วงเวลานั้น ถ้าแนวโน้มแฟลต เราจะค้นหาทิศทางแรกที่ไม่แฟลตเพื่อทราบว่าแนวโน้มมาจากไหน เพื่อแสดงลูกศรด้านข้างในสีของทิศทางนั้น
ฟังก์ชั่น Create_Panel() ในฟังก์ชั่น OnInit() ของเราจะสร้างวัตถุที่ยึดติดอยู่ที่มุมล่างซ้ายของหน้าจอและใช้ TrendPosition[] เพื่อวางลูกศรในตำแหน่งที่ถูกต้อง
//+------------------------------------------------------------------+ //| สร้างพาแนลแนวโน้มที่มุมล่างซ้ายของหน้าจอ //+------------------------------------------------------------------+ bool Create_Panel(void) { int i; string str; // สร้างหน้าต่างอินดิเคเตอร์แนวโน้ม if(ObjectCreate(TrendPanel, OBJ_RECTANGLE_LABEL, 0, 0, 0)) { ObjectSetInteger(0, TrendPanel, OBJPROP_XDISTANCE, 1); ObjectSetInteger(0, TrendPanel, OBJPROP_YDISTANCE, 29); ObjectSetInteger(0, TrendPanel, OBJPROP_XSIZE, 240); ObjectSetInteger(0, TrendPanel, OBJPROP_YSIZE, 26); ObjectSetInteger(0, TrendPanel, OBJPROP_BGCOLOR, White); ObjectSetInteger(0, TrendPanel, OBJPROP_BORDER_TYPE, 0); ObjectSetInteger(0, TrendPanel, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSetInteger(0, TrendPanel, OBJPROP_COLOR, Red); ObjectSetInteger(0, TrendPanel, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, TrendPanel, OBJPROP_WIDTH, 2); ObjectSetInteger(0, TrendPanel, OBJPROP_BACK, false); ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTED, false); ObjectSetInteger(0, TrendPanel, OBJPROP_HIDDEN, true); ObjectSetString(0, TrendPanel, OBJPROP_TOOLTIP, "\n"); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, TrendPanel, GetLastError()); return(false); } if(ObjectCreate(InfoLine1, OBJ_LABEL, 0, 0, 0)) { ObjectSet(InfoLine1, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(InfoLine1, OBJPROP_XDISTANCE, 6); ObjectSet(InfoLine1, OBJPROP_YDISTANCE, 15); ObjectSetInteger(0, InfoLine1, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, InfoLine1, OBJPROP_HIDDEN, true); ObjectSetString(0, InfoLine1, OBJPROP_TOOLTIP, "\n"); ObjectSetText(InfoLine1, TrendLabel, 8, "Arial", Black); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine1, GetLastError()); return(false); } if(ObjectCreate(InfoLine2, OBJ_LABEL, 0, 0, 0)) { ObjectSet(InfoLine2, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(InfoLine2, OBJPROP_XDISTANCE, 6); ObjectSet(InfoLine2, OBJPROP_YDISTANCE,5); ObjectSetInteger(0, InfoLine2, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, InfoLine2, OBJPROP_HIDDEN, true); ObjectSetString(0, InfoLine2, OBJPROP_TOOLTIP, "\n"); ObjectSetText(InfoLine2, " " + DoubleToStr(BarCount, 0) + " / " + DoubleToStr(Method, 0), 8, "Arial", Black); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine2, GetLastError()); return( false); } // สร้างวัตถุแนวโน้มและแสดงแนวโน้มปัจจุบัน for(i=1; i< 10; i++) { str = "Trend" + DoubleToStr(i, 0); if(ObjectCreate(str, OBJ_LABEL, 0, 0, 0)) { ObjectSet(str, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(str, OBJPROP_XDISTANCE, TrendPosition[i- 1]); ObjectSet(str, OBJPROP_YDISTANCE, 5); ObjectSetInteger( 0, str, OBJPROP_SELECTABLE, false); ObjectSetInteger( 0, str, OBJPROP_HIDDEN, true); ObjectSetString( 0, str, OBJPROP_TOOLTIP, "\n"); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, str, GetLastError()); return( false); } } // แสดงแนวโน้มปัจจุบัน DisplayTrend(); // ทุกอย่างเรียบร้อย return( true); }
ฟังก์ชั่นนี้จะส่งคืน TRUE หากการสร้างวัตถุทั้งหมดสำเร็จ หรือส่งคืน FALSE หากเกิดข้อผิดพลาดในการสร้างวัตถุ สิ่งที่ดีคืออินดิเคเตอร์จะแสดงในแท็บ EXPERT ของคอนโซลของคุณรหัสข้อผิดพลาดและหมายเลขบรรทัดของโค้ดที่เกิดข้อผิดพลาด
นอกจากนี้เรายังต้องอัปเดตอินดิเคเตอร์แนวโน้มสำหรับแต่ละ TICK ใหม่ที่เรารับมา ซึ่งทำได้โดยการเรียก DisplayTrend() ในฟังก์ชั่น start()
//+------------------------------------------------------------------+ //| ฟังก์ชั่นวนรอบของอินดิเคเตอร์ | //+------------------------------------------------------------------+ int start() { // แสดงแนวโน้มปัจจุบันสำหรับทุกช่วงเวลา DisplayTrend(); return(0); }
สุดท้ายเราจะทำลายวัตถุทั้งหมดที่สร้างโดยอินดิเคเตอร์เมื่อเราปิดอินดิเคเตอร์
//+------------------------------------------------------------------+ //| ฟังก์ชั่นการยกเลิกการเริ่มทำงาน | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // ลบวัตถุของอินดิเคเตอร์if(ObjectFind(TrendPanel) >= 0) ObjectDelete(TrendPanel); if( ObjectFind(InfoLine1) >= 0) ObjectDelete(InfoLine1); if( ObjectFind(InfoLine2) >= 0) ObjectDelete(InfoLine2); for( int i= 1; i< 10; i++) if( ObjectFind( "Trend"+ DoubleToStr(i, 0)) >= 0) ObjectDelete( "Trend"+ DoubleToStr(i, 0)); }
แค่นี้ก็เรียบร้อยแล้วครับ คุณมีพาแนลอินดิเคเตอร์ที่แสดงแนวโน้มปัจจุบันสำหรับทุกช่วงเวลาอยู่ที่มุมล่างซ้ายของหน้าจอ
ขอให้สนุกกับการเทรด!
โพสต์ที่เกี่ยวข้อง
- เครื่องมือ Open Range Breakout สำหรับ MetaTrader 5
- เครื่องมือ Master Tools - อินดิเคเตอร์สำหรับ MetaTrader 4
- FX Multi-Meter II: เครื่องมือช่วยเทรดที่ครบครันสำหรับนักลงทุน
- Volume Profile + Range v6.0: เครื่องมือวิเคราะห์การซื้อขายใน MetaTrader 5
- Bollinger Squeeze Advanced: เครื่องมือวิเคราะห์ชั้นนำสำหรับการเทรดใน MetaTrader 4