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