SiamCafe.net Blog
Technology

support/resistance mql4

supportresistance mql4
support/resistance mql4 | SiamCafe Blog
2026-02-28· อ. บอม — SiamCafe.net· 8,631 คำ

แนวรับแนวต้านคืออะไร

แนวรับ (Support) คือระดับราคาที่มีแรงซื้อ (Demand) มากพอจะหยุดราคาไม่ให้ลงต่อ เมื่อราคาลงมาถึงแนวรับ มักจะ Bounce กลับขึ้นไป แนวต้าน (Resistance) คือระดับราคาที่มีแรงขาย (Supply) มากพอจะหยุดราคาไม่ให้ขึ้นต่อ เมื่อราคาขึ้นไปถึงแนวต้าน มักจะ Bounce กลับลงมา

แนวรับแนวต้านเป็นพื้นฐานที่สำคัญที่สุดของ Technical Analysis ใช้ในการหาจุดเข้า (Entry), จุดออก (Exit), วาง Stop Loss และ Take Profit การเขียน Code ตรวจจับแนวรับแนวต้านอัตโนมัติช่วยให้ EA ทำงานได้อย่างมีประสิทธิภาพ

MQL4 Indicator — Support/Resistance Detection

//+------------------------------------------------------------------+
//| SupportResistance.mq4 — Custom Indicator                          |
//| ตรวจจับแนวรับแนวต้านด้วย Fractal Method + Clustering             |
//+------------------------------------------------------------------+
#property copyright "SiamCafe Blog"
#property version   "2.0"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrDodgerBlue    // Support
#property indicator_color2 clrOrangeRed     // Resistance
#property indicator_width1 2
#property indicator_width2 2
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID

//--- Input Parameters
input int      LookbackBars    = 200;    // จำนวนแท่งเทียนย้อนหลัง
input int      FractalPeriod   = 5;      // Fractal Period (แท่งเทียนข้างละ)
input double   ClusterRange    = 0.0010; // ระยะรวม Cluster (สำหรับ 4-digit)
input int      MinTouches      = 2;      // จำนวนครั้งที่ราคาต้อง Touch
input bool     DrawZones       = true;   // วาด Zone บนกราฟ

//--- Indicator Buffers
double SupportBuffer[];
double ResistanceBuffer[];

//--- Global Arrays
double SupportLevels[];
double ResistanceLevels[];
int    SupportStrength[];
int    ResistanceStrength[];

//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, SupportBuffer);
   SetIndexBuffer(1, ResistanceBuffer);
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(0, 159);  // Up Arrow
   SetIndexArrow(1, 159);  // Down Arrow
   
   IndicatorShortName("S/R Detector");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   int limit = MathMin(rates_total - FractalPeriod, LookbackBars);
   
   // Clear buffers
   ArrayInitialize(SupportBuffer, EMPTY_VALUE);
   ArrayInitialize(ResistanceBuffer, EMPTY_VALUE);
   
   // Step 1: หา Fractal Highs และ Lows
   double fractalHighs[];
   double fractalLows[];
   ArrayResize(fractalHighs, 0);
   ArrayResize(fractalLows, 0);
   
   for(int i = FractalPeriod; i < limit; i++)
   {
      // Fractal High
      bool isHigh = true;
      for(int j = 1; j <= FractalPeriod; j++)
      {
         if(high[i] <= high[i-j] || high[i] <= high[i+j])
         {
            isHigh = false;
            break;
         }
      }
      if(isHigh)
      {
         int size = ArraySize(fractalHighs);
         ArrayResize(fractalHighs, size + 1);
         fractalHighs[size] = high[i];
      }
      
      // Fractal Low
      bool isLow = true;
      for(int j = 1; j <= FractalPeriod; j++)
      {
         if(low[i] >= low[i-j] || low[i] >= low[i+j])
         {
            isLow = false;
            break;
         }
      }
      if(isLow)
      {
         int size = ArraySize(fractalLows);
         ArrayResize(fractalLows, size + 1);
         fractalLows[size] = low[i];
      }
   }
   
   // Step 2: Cluster ระดับราคาใกล้กัน
   ClusterLevels(fractalHighs, ResistanceLevels, ResistanceStrength);
   ClusterLevels(fractalLows, SupportLevels, SupportStrength);
   
   // Step 3: วาดบนกราฟ
   if(DrawZones)
   {
      DrawSRZones();
   }
   
   return(rates_total);
}

//+------------------------------------------------------------------+
//| รวม Level ที่ใกล้กันเป็น Cluster                                  |
//+------------------------------------------------------------------+
void ClusterLevels(double &levels[], double &clustered[],
                   int &strength[])
{
   ArrayResize(clustered, 0);
   ArrayResize(strength, 0);
   
   if(ArraySize(levels) == 0) return;
   
   // Sort
   ArraySort(levels);
   
   double currentCluster = levels[0];
   double clusterSum = levels[0];
   int clusterCount = 1;
   
   for(int i = 1; i < ArraySize(levels); i++)
   {
      if(MathAbs(levels[i] - currentCluster) <= ClusterRange)
      {
         clusterSum += levels[i];
         clusterCount++;
      }
      else
      {
         if(clusterCount >= MinTouches)
         {
            int size = ArraySize(clustered);
            ArrayResize(clustered, size + 1);
            ArrayResize(strength, size + 1);
            clustered[size] = clusterSum / clusterCount;
            strength[size] = clusterCount;
         }
         currentCluster = levels[i];
         clusterSum = levels[i];
         clusterCount = 1;
      }
   }
   
   // Last cluster
   if(clusterCount >= MinTouches)
   {
      int size = ArraySize(clustered);
      ArrayResize(clustered, size + 1);
      ArrayResize(strength, size + 1);
      clustered[size] = clusterSum / clusterCount;
      strength[size] = clusterCount;
   }
}

//+------------------------------------------------------------------+
//| วาด S/R Zones บนกราฟ                                              |
//+------------------------------------------------------------------+
void DrawSRZones()
{
   // ลบ Objects เก่า
   ObjectsDeleteAll(0, "SR_");
   
   double zoneWidth = ClusterRange / 2;
   
   for(int i = 0; i < ArraySize(SupportLevels); i++)
   {
      string name = "SR_S_" + IntegerToString(i);
      ObjectCreate(0, name, OBJ_RECTANGLE, 0,
                   Time[LookbackBars], SupportLevels[i] - zoneWidth,
                   Time[0], SupportLevels[i] + zoneWidth);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clrDodgerBlue);
      ObjectSetInteger(0, name, OBJPROP_FILL, true);
      ObjectSetInteger(0, name, OBJPROP_BACK, true);
      ObjectSetString(0, name, OBJPROP_TOOLTIP,
                      "Support: " + DoubleToString(SupportLevels[i], Digits)
                      + " (Touches: " + IntegerToString(SupportStrength[i]) + ")");
   }
   
   for(int i = 0; i < ArraySize(ResistanceLevels); i++)
   {
      string name = "SR_R_" + IntegerToString(i);
      ObjectCreate(0, name, OBJ_RECTANGLE, 0,
                   Time[LookbackBars], ResistanceLevels[i] - zoneWidth,
                   Time[0], ResistanceLevels[i] + zoneWidth);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clrOrangeRed);
      ObjectSetInteger(0, name, OBJPROP_FILL, true);
      ObjectSetInteger(0, name, OBJPROP_BACK, true);
   }
}

Pivot Points Calculator

//+------------------------------------------------------------------+
//| PivotPoints.mq4 — Pivot Points Indicator                          |
//| คำนวณ Classic, Fibonacci และ Camarilla Pivot Points               |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window

input string PivotType = "Classic"; // Classic, Fibonacci, Camarilla

void OnInit()
{
   CalculatePivots();
}

void CalculatePivots()
{
   // ดึงข้อมูลจากวันก่อน
   double prevHigh  = iHigh(Symbol(), PERIOD_D1, 1);
   double prevLow   = iLow(Symbol(), PERIOD_D1, 1);
   double prevClose = iClose(Symbol(), PERIOD_D1, 1);
   double prevOpen  = iOpen(Symbol(), PERIOD_D1, 1);
   
   double PP, R1, R2, R3, S1, S2, S3;
   
   if(PivotType == "Classic")
   {
      PP = (prevHigh + prevLow + prevClose) / 3;
      R1 = 2 * PP - prevLow;
      S1 = 2 * PP - prevHigh;
      R2 = PP + (prevHigh - prevLow);
      S2 = PP - (prevHigh - prevLow);
      R3 = prevHigh + 2 * (PP - prevLow);
      S3 = prevLow - 2 * (prevHigh - PP);
   }
   else if(PivotType == "Fibonacci")
   {
      PP = (prevHigh + prevLow + prevClose) / 3;
      double range = prevHigh - prevLow;
      R1 = PP + 0.382 * range;
      R2 = PP + 0.618 * range;
      R3 = PP + 1.000 * range;
      S1 = PP - 0.382 * range;
      S2 = PP - 0.618 * range;
      S3 = PP - 1.000 * range;
   }
   else // Camarilla
   {
      double range = prevHigh - prevLow;
      PP = (prevHigh + prevLow + prevClose) / 3;
      R1 = prevClose + range * 1.1 / 12;
      R2 = prevClose + range * 1.1 / 6;
      R3 = prevClose + range * 1.1 / 4;
      S1 = prevClose - range * 1.1 / 12;
      S2 = prevClose - range * 1.1 / 6;
      S3 = prevClose - range * 1.1 / 4;
   }
   
   // วาดเส้นบนกราฟ
   DrawLevel("PP", PP, clrYellow, STYLE_SOLID);
   DrawLevel("R1", R1, clrRed, STYLE_DASH);
   DrawLevel("R2", R2, clrRed, STYLE_DASHDOT);
   DrawLevel("R3", R3, clrRed, STYLE_SOLID);
   DrawLevel("S1", S1, clrDodgerBlue, STYLE_DASH);
   DrawLevel("S2", S2, clrDodgerBlue, STYLE_DASHDOT);
   DrawLevel("S3", S3, clrDodgerBlue, STYLE_SOLID);
   
   Comment(StringFormat(
      "%s Pivot Points\nR3: %.5f\nR2: %.5f\nR1: %.5f\n"
      "PP: %.5f\nS1: %.5f\nS2: %.5f\nS3: %.5f",
      PivotType, R3, R2, R1, PP, S1, S2, S3));
}

void DrawLevel(string name, double price, color clr, int style)
{
   string objName = "Pivot_" + name;
   ObjectDelete(objName);
   ObjectCreate(0, objName, OBJ_HLINE, 0, 0, price);
   ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
   ObjectSetInteger(0, objName, OBJPROP_STYLE, style);
   ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1);
   ObjectSetString(0, objName, OBJPROP_TEXT, name + ": " +
                   DoubleToString(price, Digits));
}

Python Script วิเคราะห์ S/R จากข้อมูลจริง

# sr_analysis.py — วิเคราะห์ Support/Resistance ด้วย Python
import numpy as np
from collections import defaultdict

class SupportResistanceDetector:
    """ตรวจจับแนวรับแนวต้านจากข้อมูลราคา"""

    def __init__(self, cluster_pct=0.1, min_touches=2):
        self.cluster_pct = cluster_pct / 100  # % ของราคา
        self.min_touches = min_touches

    def find_fractals(self, highs, lows, period=5):
        """หา Fractal Highs/Lows"""
        frac_highs, frac_lows = [], []

        for i in range(period, len(highs) - period):
            # Fractal High
            if all(highs[i] > highs[i-j] for j in range(1, period+1)) and \
               all(highs[i] > highs[i+j] for j in range(1, period+1)):
                frac_highs.append(highs[i])

            # Fractal Low
            if all(lows[i] < lows[i-j] for j in range(1, period+1)) and \
               all(lows[i] < lows[i+j] for j in range(1, period+1)):
                frac_lows.append(lows[i])

        return frac_highs, frac_lows

    def cluster_levels(self, levels):
        """รวม Level ที่ใกล้กัน"""
        if not levels:
            return []

        sorted_levels = sorted(levels)
        clusters = []
        current = [sorted_levels[0]]

        for level in sorted_levels[1:]:
            if abs(level - np.mean(current)) / np.mean(current) <= self.cluster_pct:
                current.append(level)
            else:
                if len(current) >= self.min_touches:
                    clusters.append({
                        "price": round(np.mean(current), 5),
                        "touches": len(current),
                        "strength": len(current),
                    })
                current = [level]

        if len(current) >= self.min_touches:
            clusters.append({
                "price": round(np.mean(current), 5),
                "touches": len(current),
                "strength": len(current),
            })

        return clusters

    def detect(self, highs, lows, closes):
        """ตรวจจับ Support/Resistance"""
        frac_highs, frac_lows = self.find_fractals(highs, lows)

        resistance = self.cluster_levels(frac_highs)
        support = self.cluster_levels(frac_lows)

        current_price = closes[-1]

        # แยก Active Levels (ใกล้ราคาปัจจุบัน)
        active_support = [s for s in support if s["price"] < current_price]
        active_resistance = [r for r in resistance if r["price"] > current_price]

        # Sort by distance
        active_support.sort(key=lambda x: current_price - x["price"])
        active_resistance.sort(key=lambda x: x["price"] - current_price)

        return {
            "support": active_support[:5],
            "resistance": active_resistance[:5],
            "current_price": current_price,
        }

# ตัวอย่าง
np.random.seed(42)
n = 500
prices = 1.1000 + np.cumsum(np.random.randn(n) * 0.001)
highs = prices + np.abs(np.random.randn(n) * 0.0005)
lows = prices - np.abs(np.random.randn(n) * 0.0005)

detector = SupportResistanceDetector(cluster_pct=0.15, min_touches=2)
result = detector.detect(highs, lows, prices)

print(f"Current Price: {result['current_price']:.5f}")
print(f"\nSupport Levels:")
for s in result["support"]:
    print(f"  {s['price']:.5f} (touches: {s['touches']})")
print(f"\nResistance Levels:")
for r in result["resistance"]:
    print(f"  {r['price']:.5f} (touches: {r['touches']})")

Trading Strategies กับ S/R

แนวรับแนวต้าน (Support/Resistance) คืออะไร

แนวรับคือระดับราคาที่มีแรงซื้อหยุดราคาไม่ให้ลงต่อ แนวต้านคือระดับที่มีแรงขายหยุดราคาไม่ให้ขึ้นต่อ เกิดจากจุดที่ราคาเคย Bounce กลับหลายครั้ง เป็นพื้นฐาน Technical Analysis

วิธีหาแนวรับแนวต้านด้วย Code ทำอย่างไร

ใช้ Fractal Method หาจุด High/Low ที่สูงหรือต่ำกว่าแท่งข้างเคียง Pivot Points คำนวณจาก OHLC วันก่อน Volume Profile หาระดับที่มี Volume สูง Clustering รวมระดับใกล้กันเป็นโซนเดียว

Pivot Points คำนวณอย่างไร

Classic: PP = (H+L+C)/3 R1 = 2*PP-L S1 = 2*PP-H R2 = PP+(H-L) S2 = PP-(H-L) มีหลายแบบ Classic Fibonacci Camarilla Woodie แต่ละแบบเหมาะกับสภาวะตลาดต่างกัน

ควรใช้ Timeframe ไหนหา Support/Resistance

Daily และ Weekly มีน้ำหนักมากที่สุด เหมาะ Intraday M30 สำหรับ Scalping ใช้หลาย Timeframe ร่วมกัน (Multi-timeframe Analysis) S/R จาก Timeframe ใหญ่สำคัญกว่า Timeframe เล็ก

สรุป

Support/Resistance เป็นพื้นฐานสำคัญของ Technical Analysis การเขียน MQL4 Indicator ตรวจจับอัตโนมัติด้วย Fractal Method และ Clustering ช่วยให้หาแนวรับแนวต้านได้แม่นยำ Pivot Points ให้ระดับราคาสำคัญจาก OHLC วันก่อน ใช้ร่วมกับ Trading Strategy เช่น Bounce, Breakout, Retest และ Multi-timeframe Analysis สิ่งสำคัญคือ S/R เป็นโซนไม่ใช่เส้น และ Timeframe ใหญ่มีน้ำหนักมากกว่า

📖 บทความที่เกี่ยวข้อง

mql4 ontickอ่านบทความ → mql4 programming courseอ่านบทความ → mql4 volume indicatorอ่านบทความ → mql4 ordersend without stop lossอ่านบทความ → mql4 ea exampleอ่านบทความ →

📚 ดูบทความทั้งหมด →