246 lines
No EOL
8.8 KiB
MQL5
246 lines
No EOL
8.8 KiB
MQL5
|
|
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
|
|
#include <Trade\Trade.mqh>
|
|
//+------------------------------------------------------------------+
|
|
//| 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 InpMAPeriod = 21; // ma period
|
|
input ENUM_TIMEFRAMES InpMATimeframe = PERIOD_H1; // ma timeframe
|
|
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 by opposite signal
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Global variable |
|
|
//+------------------------------------------------------------------+
|
|
int handleRSI;
|
|
int handleMA;
|
|
double bufferRSI[];
|
|
double bufferMA[];
|
|
MqlTick currentTick;
|
|
CTrade trade;
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 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(InpMAPeriod <= 1 ){
|
|
Print("Failed to use the RSI Period");
|
|
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;
|
|
}
|
|
if(InpStopLoss <= 0 && InpCloseSignal ){
|
|
Print("stoploss and close signal are 0 at the same time!! really big risk!!");
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
// set Magic number
|
|
trade.SetExpertMagicNumber(InpMagicnumber);
|
|
|
|
// create rsi handleRSI
|
|
handleRSI = iRSI(_Symbol,PERIOD_CURRENT,InpRSIPeriod,PRICE_OPEN);
|
|
if(handleRSI == INVALID_HANDLE){
|
|
Print("failed to create indicator handleRSI");
|
|
return INIT_FAILED ;
|
|
}
|
|
|
|
handleMA = iMA(_Symbol,InpMATimeframe,PRICE_OPEN,0,MODE_SMA,PRICE_OPEN);
|
|
if(handleRSI == INVALID_HANDLE){
|
|
Print("failed to create indicator handleMA");
|
|
return INIT_FAILED ;
|
|
}
|
|
|
|
//set buffer as series ## for setting the series , it makes the latest data placed in [0]
|
|
ArraySetAsSeries(bufferRSI,true);
|
|
ArraySetAsSeries(bufferMA,true);
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason){
|
|
|
|
// release indicator handleRSI
|
|
if(handleRSI!=INVALID_HANDLE){IndicatorRelease(handleRSI);}
|
|
if(handleMA!=INVALID_HANDLE){IndicatorRelease(handleMA);}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick(){
|
|
|
|
//check if current tick is a new bar open tick
|
|
if(!IsNewBar()){return;}
|
|
|
|
//get current tick
|
|
if(!SymbolInfoTick(_Symbol,currentTick)){
|
|
Print("Failed to get current tick");
|
|
return;
|
|
}
|
|
|
|
//get rsi values and copy the array to bufferRSI
|
|
int values = CopyBuffer(handleRSI,0,0,2,bufferRSI);
|
|
if(values!=2){
|
|
Print("Failed to get RSI values");
|
|
return;
|
|
}
|
|
|
|
//get rsi values and copy the array to bufferRSI
|
|
values = CopyBuffer(handleMA,0,0,1,bufferMA);
|
|
if(values!=1){
|
|
Print("Failed to get MA values");
|
|
return;
|
|
}
|
|
|
|
Comment("bufferRSI[0]:", bufferRSI[0],
|
|
"\nbufferRSI[1]" , bufferRSI[1],
|
|
"\nbufferMA[0]:", bufferMA[0]);
|
|
|
|
//count open psoitions
|
|
int cntBuy, cntSell;
|
|
if(!CountOpenPositions(cntBuy,cntSell)){return;}
|
|
|
|
//check for buy position
|
|
if(cntBuy==0 && bufferRSI[1]>=(100-InpRSILevel) && bufferRSI[0]<(100-InpRSILevel) && currentTick.ask>bufferMA[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 MA filter EA");
|
|
}
|
|
|
|
//check for sell position
|
|
if(cntSell==0 && bufferRSI[1]<=InpRSILevel && bufferRSI[0]>InpRSILevel && currentTick.bid<bufferMA[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 |
|
|
//+------------------------------------------------------------------+
|
|
|
|
// check if we have a bar open tick
|
|
bool IsNewBar(){
|
|
|
|
static datetime previousTime = 0;
|
|
datetime currentTime = iTime(_Symbol,PERIOD_CURRENT,0);
|
|
if(previousTime!=currentTime){
|
|
previousTime=currentTime;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 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;}
|
|
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(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;
|
|
} |