//+------------------------------------------------------------------+ //| RsiEA.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include //+------------------------------------------------------------------+ //| Input | //+------------------------------------------------------------------+ static input long InpMagicnumber = 778973; //magicnumber static input double InpLotSize = 0.01; // lot size input int InpRSIPeriod = 21; // rsi period input int InpRSILevel = 70; //rsi level (upper) input int InpStopLoss = 200; // stop loss in point (0 = off) input int InpTakeProfit = 100; // take profit in points (0=off) input bool InpCloseSignal = false; // close trades bu opposite signal //+------------------------------------------------------------------+ //| Global variable | //+------------------------------------------------------------------+ int handle; double buffer[]; MqlTick currentTick; CTrade trade; datetime openTimeBuy = 0; datetime openTimeSell = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(){ // check user input if(InpMagicnumber <= 0){ Print("Failed to use the MagicNumber because it is below 0"); return INIT_PARAMETERS_INCORRECT; } if(InpLotSize <= 0 || InpLotSize > 10 ){ Print("Failed to use the Lotsize"); return INIT_PARAMETERS_INCORRECT; } if(InpRSIPeriod <= 1 ){ Print("Failed to use the RSI Period"); return INIT_PARAMETERS_INCORRECT; } if(InpRSILevel >= 100 || InpRSILevel <=50){ Print("Wrong input of RSI LEVEL"); return INIT_PARAMETERS_INCORRECT; } if(InpStopLoss < 0 ){ Print("Wrong input of Stoploss"); return INIT_PARAMETERS_INCORRECT; } if(InpTakeProfit < 0 ){ Print("Wrong input of TakeProfit"); return INIT_PARAMETERS_INCORRECT; } // set Magic number trade.SetExpertMagicNumber(InpMagicnumber); // create rsi handle handle = iRSI(_Symbol,PERIOD_CURRENT,InpRSIPeriod,PRICE_CLOSE); if(handle == INVALID_HANDLE){ Print("failed to create indicator handle"); return INIT_FAILED ; } //set buffer as series ## for setting the series , it makes the latest data placed in [0] ArraySetAsSeries(buffer,true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason){ // release indicator handle if(handle!=INVALID_HANDLE){IndicatorRelease(handle);} } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(){ //get current tick if(!SymbolInfoTick(_Symbol,currentTick)){ Print("Failed to get current tick"); return; } //get rsi values and copy the array to buffer int values = CopyBuffer(handle,0,0,2,buffer); if(values!=2){ Print("Failed to get indicator values"); return; } Comment("buffer[0]:", buffer[0], "/nbuffer[1]:", buffer[1]); //count open psoitions int cntBuy, cntSell; if(!CountOpenPositions(cntBuy,cntSell)){return;} //check for buy position if(cntBuy==0 && buffer[1]>=(100-InpRSILevel) && buffer[0]<(100-InpRSILevel) && openTimeBuy!=iTime(_Symbol,PERIOD_CURRENT,0)){ openTimeBuy=iTime(_Symbol,PERIOD_CURRENT,0); if(InpCloseSignal){if(!ClosePositions(2)){return;}} double sl = InpStopLoss==0 ? 0 : currentTick.bid - InpStopLoss * _Point; double tp = InpTakeProfit==0 ? 0 : currentTick.bid + InpTakeProfit * _Point; if(!NormalizePrice(sl)){return;} if(!NormalizePrice(tp)){return;} trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,InpLotSize,currentTick.ask,sl,tp,"RSI EA"); } //check for sell position if(cntBuy==0 && buffer[1]<=InpRSILevel && buffer[0]>InpRSILevel && openTimeSell!=iTime(_Symbol,PERIOD_CURRENT,0)){ openTimeSell=iTime(_Symbol,PERIOD_CURRENT,0); if(InpCloseSignal){if(!ClosePositions(1)){return;}} double sl = InpStopLoss ==0 ? 0 : currentTick.ask + InpStopLoss * _Point; double tp = InpTakeProfit ==0 ? 0 : currentTick.ask - InpTakeProfit * _Point; if(!NormalizePrice(sl)){return;} if(!NormalizePrice(tp)){return;} trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,InpLotSize,currentTick.bid,sl,tp,"RSI EA"); } } //+------------------------------------------------------------------+ //| Customer Function | //+------------------------------------------------------------------+ // count open positions bool CountOpenPositions(int &cntBuy, int&cntSell){ cntBuy = 0; cntSell = 0; int total = PositionsTotal(); for(int i= total-1; i>=0; i--){ ulong ticket = PositionGetTicket(i); if(ticket<=0){Print("Failed to get position ticket"); return false;} if(!PositionSelectByTicket(ticket)){Print("Failed to select position"); return false;}// тиккет может быть от позиций открытых другим экспертом, нельзя возвращать false long magic; if(!PositionGetInteger(POSITION_MAGIC,magic)) {Print("Failed to get position magicnumber"); return false;}// магик может быть от позиций открытых другим экспертом, нельзя возвращать false if(magic==InpMagicnumber){ long type; if(!PositionGetInteger(POSITION_TYPE,type)) {Print("Failed to get position type"); return false;} if(type==POSITION_TYPE_BUY) {cntBuy++ ;} if(type==POSITION_TYPE_SELL) {cntSell++ ;} } } return true; } // normalize price bool NormalizePrice(double &price){ double tickSize=0; if(!SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE,tickSize)){ Print("Failed to get tick size"); return false; } price = NormalizeDouble((MathRound(price/tickSize)*tickSize),_Digits); return true; } //close positions bool ClosePositions(int all_buy_sell){ int total = PositionsTotal(); for(int i = total-1; i>=0; i--){ ulong ticket = PositionGetTicket(i); if(ticket<=0){Print("Failed to get position ticket"); return false;} if(!PositionSelectByTicket(ticket)){Print("Failed to select position"); return false;} long magic; if(!PositionGetInteger(POSITION_MAGIC,magic)) {Print("Failed to get position magicnumber"); return false;} if(magic==InpMagicnumber){ long type; if(!PositionGetInteger(POSITION_TYPE,type)){Print("Failed to get position type"); return false;} if(all_buy_sell==1 && type==POSITION_TYPE_SELL){continue;} //1 = buy position if(all_buy_sell==2 && type==POSITION_TYPE_BUY){continue;} //2 = sell position trade.PositionClose(ticket); if(trade.ResultRetcode()!=TRADE_RETCODE_DONE){ Print("Failed to close position. Ticket:", (string)ticket," result:",(string)trade.ResultRetcode(),":",trade.CheckResultRetcodeDescription()); } } } return true; }