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

//+------------------------------------------------------------------+
//| 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)





