Thanhanh9/Test / RSI_System.mq5
download
raw
15.7 kB
//+------------------------------------------------------------------+
//| RSI System v3 – MT5 Expert Advisor |
//| Chuyển đổi từ Pine Script rsi.pine |
//| |
//| Logic: |
//| - RSI(13) tính trên giá Close |
//| - MA Fast(20) & MA Slow(100) trên RSI |
//| - Entry Buy : RSI >= 55 và MA Fast cắt lên MA Slow, Close > EMA100 |
//| - Entry Sell: RSI <= 45 và MA Fast cắt xuống MA Slow, Close < EMA100 |
//| - Exit: Trailing SL (ATR×Mult) hoặc khi MA cắt ngược |
//+------------------------------------------------------------------+
#property copyright "RSI System v3"
#property version "3.00"
#property strict
//--- Inputs: RSI
input int RSI_Length = 13; // RSI Length
input double BuyThreshold = 51.0; // RSI Buy Threshold (>=)
input double SellThreshold = 49.0; // RSI Sell Threshold (<=)
input ulong MagicNumber = 999; // Magic Number
//--- Inputs: MA trên RSI
input int MA_Slow_Length = 100; // MA Slow Length
input int MA_Fast_Length = 20; // MA Fast Length
input double MA_Dist_Thresh = 10.0; // MA Max Distance (thay thế crossover)
//--- Inputs: Trailing SL
input bool UseTrailingStop = true; // Dùng Trailing SL theo ATR
input int ATR_Length = 14; // ATR Length
input double ATR_Multiplier = 2.5; // ATR Multiplier
input double RR_Ratio = 5.0; // Take Profit (R:R)
input double Risk_Percent = 0.5; // Risk mỗi lệnh (% vốn)
//--- Handles chỉ báo
int handleRSI;
int handleMASlow;
int handleMAFast;
int handleATR;
int handleEMA100;
//+------------------------------------------------------------------+
//| Expert initialization |
//+------------------------------------------------------------------+
int OnInit()
{
// RSI(Close, RSI_Length)
handleRSI = iRSI(_Symbol, PERIOD_CURRENT, RSI_Length, PRICE_CLOSE);
if(handleRSI == INVALID_HANDLE) { Print("Lỗi tạo RSI handle"); return INIT_FAILED; }
// SMA của RSI (MA Slow & MA Fast)
handleMASlow = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Length, 0, MODE_SMA, handleRSI);
handleMAFast = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Length, 0, MODE_SMA, handleRSI);
if(handleMASlow == INVALID_HANDLE || handleMAFast == INVALID_HANDLE)
{ Print("Lỗi tạo MA Slow/Fast handle"); return INIT_FAILED; }
// ATR
handleATR = iATR(_Symbol, PERIOD_CURRENT, ATR_Length);
if(handleATR == INVALID_HANDLE) { Print("Lỗi tạo ATR handle"); return INIT_FAILED; }
// EMA(Close, 100)
handleEMA100 = iMA(_Symbol, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE);
if(handleEMA100 == INVALID_HANDLE) { Print("Lỗi tạo EMA100 handle"); return INIT_FAILED; }
Print("RSI System v3 EA khởi động thành công.");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
IndicatorRelease(handleRSI);
IndicatorRelease(handleMASlow);
IndicatorRelease(handleMAFast);
IndicatorRelease(handleATR);
IndicatorRelease(handleEMA100);
}
//+------------------------------------------------------------------+
//| Helper: Gửi lệnh và kiểm tra kết quả |
//+------------------------------------------------------------------+
bool SendOrder(MqlTradeRequest &req, MqlTradeResult &res)
{
bool ok = OrderSend(req, res);
if(!ok)
Print("OrderSend thất bại – retcode: ", res.retcode,
" comment: ", res.comment);
return ok;
}
//+------------------------------------------------------------------+
//| Helper: Đọc giá trị buffer tại vị trí shift |
//+------------------------------------------------------------------+
double GetValue(int handle, int shift = 1)
{
double buf[1];
if(CopyBuffer(handle, 0, shift, 1, buf) < 1) return EMPTY_VALUE;
return buf[0];
}
//+------------------------------------------------------------------+
//| Helper: Tính lot size theo % risk và khoảng SL |
//+------------------------------------------------------------------+
double CalcLotSize(double slDistPoints)
{
if(slDistPoints <= 0) return 0.01;
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double riskAmount = equity * Risk_Percent / 100.0;
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
if(tickSize <= 0 || tickValue <= 0) return 0.01;
// riskAmount = lot × (slDistPoints/tickSize) × tickValue
double lotRaw = riskAmount / (slDistPoints / tickSize * tickValue);
double lotMin = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double lotMax = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
lotRaw = MathFloor(lotRaw / lotStep) * lotStep;
lotRaw = MathMax(lotMin, MathMin(lotMax, lotRaw));
return lotRaw;
}
//+------------------------------------------------------------------+
//| Helper: Lấy trạng thái các vị thế hiện tại |
//+------------------------------------------------------------------+
void GetPositionsState(bool& isLong, bool& isShort)
{
isLong = false;
isShort = false;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionSelectByTicket(PositionGetTicket(i)))
{
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) isLong = true;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) isShort = true;
}
}
}
}
//+------------------------------------------------------------------+
//| Helper: Lấy Filling Mode hỗ trợ |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE_FILLING GetFillingMode()
{
int filling = (int)SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
if((filling & SYMBOL_FILLING_FOK) != 0) return ORDER_FILLING_FOK;
if((filling & SYMBOL_FILLING_IOC) != 0) return ORDER_FILLING_IOC;
return ORDER_FILLING_RETURN;
}
//+------------------------------------------------------------------+
//| Helper: Đóng tất cả vị thế theo loại |
//+------------------------------------------------------------------+
void ClosePositions(ENUM_POSITION_TYPE posType)
{
MqlTradeRequest req = {};
MqlTradeResult res = {};
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != posType) continue;
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.volume = PositionGetDouble(POSITION_VOLUME);
req.type = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
req.price = (posType == POSITION_TYPE_BUY)
? SymbolInfoDouble(_Symbol, SYMBOL_BID)
: SymbolInfoDouble(_Symbol, SYMBOL_ASK);
req.deviation = 10;
req.type_filling = GetFillingMode();
req.magic = MagicNumber;
req.position = ticket;
req.comment = "RSI_System Close";
SendOrder(req, res);
}
}
//+------------------------------------------------------------------+
//| Helper: Cập nhật Trailing SL cho tất cả vị thế cùng loại |
//+------------------------------------------------------------------+
void UpdateTrailingStop(ENUM_POSITION_TYPE posType)
{
// Đọc ATR và Giá hiện tại
double atr = GetValue(handleATR, 1);
if(atr == EMPTY_VALUE) return;
double slDist = atr * ATR_Multiplier;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != posType) continue;
double currentSL = PositionGetDouble(POSITION_SL);
double currentTP = PositionGetDouble(POSITION_TP);
MqlTradeRequest req = {};
MqlTradeResult res = {};
req.action = TRADE_ACTION_SLTP;
req.symbol = _Symbol;
req.position = ticket;
req.tp = currentTP;
if(posType == POSITION_TYPE_BUY)
{
// Logic Pine Script: math.max(trailSL, close - atr * mult)
// Ở MT5 dùng Bid (giá hiện tại) thay cho Close
double potentialSL = NormalizeDouble(bid - slDist, _Digits);
// Đảm bảo không vi phạm khoảng cách tối thiểu của sàn
double maxAllowedSL = NormalizeDouble(bid - stopLevel - _Point, _Digits);
if(potentialSL > maxAllowedSL) potentialSL = maxAllowedSL;
// Chỉ cập nhật nếu SL mới CAO HƠN SL cũ (Dịch lên)
if(potentialSL > currentSL + _Point)
{
req.sl = potentialSL;
SendOrder(req, res);
}
}
else // POSITION_TYPE_SELL
{
// Logic Pine Script: math.min(trailSL, close + atr * mult)
double potentialSL = NormalizeDouble(ask + slDist, _Digits);
// Đảm bảo không vi phạm khoảng cách tối thiểu của sàn
double minAllowedSL = NormalizeDouble(ask + stopLevel + _Point, _Digits);
if(potentialSL < minAllowedSL) potentialSL = minAllowedSL;
// Chỉ cập nhật nếu SL mới THẤP HƠN SL cũ (Dịch xuống)
if(currentSL == 0 || potentialSL < currentSL - _Point)
{
req.sl = potentialSL;
SendOrder(req, res);
}
}
}
}
//+------------------------------------------------------------------+
//| OnTick |
//+------------------------------------------------------------------+
void OnTick()
{
// --- PHẦN 1: TRAILING SL (CHẠY THEO TỪNG TICK) ---
// Logic này phải chạy liên tục để SL bám sát giá (math.max/math.min trong Pine Script)
if(UseTrailingStop)
{
UpdateTrailingStop(POSITION_TYPE_BUY);
UpdateTrailingStop(POSITION_TYPE_SELL);
}
// --- PHẦN 2: KIỂM TRA NẾN MỚI ---
// Chỉ thực hiện tính toán chỉ báo và vào lệnh khi nến hiện tại đã đóng
static datetime lastBarTime = 0;
datetime curBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
if(curBarTime == lastBarTime) return; // Nếu chưa qua nến mới thì dừng ở đây
lastBarTime = curBarTime;
// --- PHẦN 3: ĐỌC DỮ LIỆU CHỈ BÁO (BAR 1 LÀ NẾN VỪA ĐÓNG) ---
double rsi = GetValue(handleRSI, 1);
double maFast0 = GetValue(handleMAFast, 1);
double maFast1 = GetValue(handleMAFast, 2); // Nến trước đó nữa để tính Cross
double maSlow0 = GetValue(handleMASlow, 1);
double maSlow1 = GetValue(handleMASlow, 2);
double atr = GetValue(handleATR, 1);
double ema100 = GetValue(handleEMA100, 1);
double closeBar = iClose(_Symbol, PERIOD_CURRENT, 1);
if(rsi == EMPTY_VALUE || maFast0 == EMPTY_VALUE || maSlow0 == EMPTY_VALUE ||
atr == EMPTY_VALUE || ema100 == EMPTY_VALUE) return;
// --- PHẦN 4: LOGIC GIAO CẮT (CROSSOVER/CROSSUNDER) ---
bool crossUp = (maFast1 <= maSlow1) && (maFast0 > maSlow0);
bool crossDown = (maFast1 >= maSlow1) && (maFast0 < maSlow0);
double maDist = maFast0 - maSlow0;
// MA signal: Cắt nhau HOẶC đang nằm trên/dưới nhưng trong khoảng cách cho phép
bool maSignalUp = crossUp || (maDist > 0 && maDist < MA_Dist_Thresh);
bool maSignalDown = crossDown || (maDist < 0 && MathAbs(maDist) < MA_Dist_Thresh);
// --- Lấy trạng thái hiện tại ---
bool isLong, isShort;
GetPositionsState(isLong, isShort);
// --- PHẦN 5: ĐÓNG LỆNH KHI MA CẮT NGƯỢC (EXIT LOGIC) ---
if(isLong && crossDown)
{
Print("MA Cross Exit Buy");
ClosePositions(POSITION_TYPE_BUY);
isLong = false;
}
if(isShort && crossUp)
{
Print("MA Cross Exit Sell");
ClosePositions(POSITION_TYPE_SELL);
isShort = false;
}
// --- PHẦN 6: VÀO LỆNH MỚI (CHỈ KHI CHƯA CÓ VỊ THẾ) ---
if(!isLong && !isShort)
{
// Điều kiện Buy: RSI >= 51, MA Signal Up, Giá > EMA100
if(rsi >= BuyThreshold && maSignalUp && closeBar > ema100)
{
double slDist = atr * ATR_Multiplier;
double slPrice = NormalizeDouble(closeBar - slDist, _Digits);
double tpPrice = NormalizeDouble(closeBar + slDist * RR_Ratio, _Digits);
double lot = CalcLotSize(slDist);
MqlTradeRequest req = {};
MqlTradeResult res = {};
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.volume = lot;
req.type = ORDER_TYPE_BUY;
req.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
req.sl = slPrice;
req.tp = tpPrice;
req.deviation = 10;
req.type_filling = GetFillingMode();
req.magic = MagicNumber;
req.comment = "RSI_System Buy";
SendOrder(req, res);
}
// Điều kiện Sell: RSI <= 49, MA Signal Down, Giá < EMA100
else if(rsi <= SellThreshold && maSignalDown && closeBar < ema100)
{
double slDist = atr * ATR_Multiplier;
double slPrice = NormalizeDouble(closeBar + slDist, _Digits);
double tpPrice = NormalizeDouble(closeBar - slDist * RR_Ratio, _Digits);
double lot = CalcLotSize(slDist);
MqlTradeRequest req = {};
MqlTradeResult res = {};
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.volume = lot;
req.type = ORDER_TYPE_SELL;
req.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
req.sl = slPrice;
req.tp = tpPrice;
req.deviation = 10;
req.type_filling = GetFillingMode();
req.magic = MagicNumber;
req.comment = "RSI_System Sell";
SendOrder(req, res);
}
}
}
//+------------------------------------------------------------------+

Xet Storage Details

Size:
15.7 kB
·
Xet hash:
dc78bb9305568a6a3893ba89283077e9b07450da2bdd7dc936b58185e25628d5

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.