trade

Support Resistance MQL4 — วิธีเขียน Indicator

Support Resistance MQL4 — วิธีเขียน Indicator

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

Support Resistance MQL4 — วิธีเขียน Indicator

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

เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ Ceph Distributed Storage สร้าง Storage Cluster ที่บ้าน

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

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง m1 finance vs webull

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

Support Resistance MQL4 — วิธีเขียน Indicator
//+------------------------------------------------------------------+
//| 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

  • Bounce Trading: เปิด Buy ที่แนวรับ เปิด Sell ที่แนวต้าน SL อีกด้านของ Zone TP ที่ S/R ถัดไป
  • Breakout Trading: เปิด Buy เมื่อราคาทะลุแนวต้าน เปิด Sell เมื่อทะลุแนวรับ รอ Confirmation ก่อนเข้า
  • Retest Strategy: รอ Breakout แล้วรอราคากลับมา Retest Level เดิม จึงเข้า Trade ลด False Breakout
  • Multi-timeframe: หา S/R จาก Daily แล้วเข้า Trade บน H1 หรือ S/R จาก Timeframe ใหญ่มีน้ำหนักมากกว่า

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

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

แนะนำเพิ่มเติม — SiamCafeBook

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง Data Lakehouse Career Development IT

เริ่มต้นเทรด Forex กับ XM — โบรกที่ อ.บอม ใช้เทรดจริง (พาร์ทเนอร์ XM)

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง