#property copyright "Copyright 2023, M & Q Investment Group" #property link "https://www.mql5.com" #property version "1.00" #include CTrade trade; input double IndiTrendMiniValue = 10; input int INDIEvaluRangeMin = 100; int INDIEvaluRangeSec = INDIEvaluRangeMin * 60; double MinTrendValue = 20; input int RSIOverboughtlevel = 70; input int RSIOversoldlevel = 30; input int GHighLowShift = 10; input double GMaximalSLPoints = 100; input double GMaximalTPPoints = 100; input double GTPtoOneSLRatio = 1; input double RiskPerc = 1; input double GTrigTSLRatioPricebeforeTP = 0.5; input int GMinTSLDistPoints = 50; input int TradecooldownMin = 30; int TradecooldownSec = TradecooldownMin * 60; datetime Tradecooldown; int HandleRSI; int HandleATR; int HandleMA200; int HandleMA50; int HandleMA21; double accountbalancebeginning; double accountprofit; double Lostrades = 0; double Wintrades = 0; double AllWinRatio = 0; int OnInit(){ HandleRSI = iRSI(_Symbol,PERIOD_CURRENT,14,PRICE_CLOSE); HandleATR = iATR(_Symbol,PERIOD_CURRENT,14); HandleMA200 = iMA(_Symbol,PERIOD_CURRENT,200,0,MODE_SMMA,PRICE_CLOSE); HandleMA50 = iMA(_Symbol,PERIOD_CURRENT,50,0,MODE_SMMA,PRICE_CLOSE); HandleMA21 = iMA(_Symbol,PERIOD_CURRENT,21,0,MODE_SMMA,PRICE_CLOSE); accountbalancebeginning = AccountInfoDouble(ACCOUNT_BALANCE); return(INIT_SUCCEEDED); } void OnDeinit(const int reason){ Lostrades = TesterStatistics(STAT_LOSS_TRADES); Wintrades = TesterStatistics(STAT_PROFIT_TRADES); if(Lostrades + Wintrades > 0){ AllWinRatio = NormalizeDouble(Wintrades / (Wintrades + Lostrades),2); }else{AllWinRatio = 0;} Print("Verlorene Trades: ",Lostrades, "\nGewonnenen Trades: ",Wintrades, "\nGewinnrate:________",AllWinRatio); } void OnTick(){ datetime Currenttime = TimeCurrent(); double RSITrend = CheckINDITrend(Currenttime,INDIEvaluRangeSec,HandleRSI,true); double MA21Trend = CheckINDITrend(Currenttime,INDIEvaluRangeSec,HandleMA21,false); double MA50Trend = CheckINDITrend(Currenttime,INDIEvaluRangeSec,HandleMA50,false); double RSICurrentValue[]; CopyBuffer(HandleRSI,0,0,1,RSICurrentValue); Comment("\n RSITrend: ",RSITrend, "\n MA21Trend: ",MA21Trend, "\n MA50Trend: ",MA50Trend); if(PositionsTotal() == 0 && OrdersTotal() == 0 && Currenttime > Tradecooldown){ double IndiTrendMiniValueNeg = IndiTrendMiniValue * - 1; double SL = 0; double TP = 0; double Lots = 0; double Price = 0; double RiskSplitPerc = RiskPerc / 1; // --- IMPORTANT LOTCALC string TradeComment ="RSITrend: "+ DoubleToString(RSITrend,0) + " MA21Trend: " + DoubleToString(MA21Trend,0) + " MA50Trend: " + DoubleToString(MA50Trend,0); //SELLTREND if(RSITrend < IndiTrendMiniValueNeg && MA21Trend < IndiTrendMiniValueNeg && MA50Trend < IndiTrendMiniValueNeg && RSICurrentValue[0] > RSIOversoldlevel){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); SL = CalcSL(false,GHighLowShift,HandleATR,GMaximalSLPoints); TP = CalcTP(false,SL,GMaximalTPPoints,GTPtoOneSLRatio); Lots = CalcLots(RiskSplitPerc,MathAbs(Price - SL)); trade.Sell(Lots,_Symbol,Price,SL,TP,TradeComment); //trade.Sell(Lots,_Symbol,Price,SL,TP,TradeComment); //trade.Sell(Lots,_Symbol,Price,SL,TP,"TSL-Trade"); Tradecooldown = Currenttime + TradecooldownSec; } //BUYTREND if(RSITrend > IndiTrendMiniValue && MA21Trend > IndiTrendMiniValue && MA50Trend > IndiTrendMiniValue && RSICurrentValue[0] < RSIOverboughtlevel){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); SL = CalcSL(true,GHighLowShift,HandleATR,GMaximalSLPoints); TP = CalcTP(true,SL,GMaximalTPPoints,GTPtoOneSLRatio); Lots = CalcLots(RiskSplitPerc,MathAbs(Price - SL)); trade.Buy(Lots,_Symbol,Price,SL,TP,TradeComment); //trade.Buy(Lots,_Symbol,Price,SL,TP,TradeComment); //trade.Buy(Lots,_Symbol,Price,SL,TP,"TSL-Trade"); Tradecooldown = Currenttime + TradecooldownSec; } } /*if(PositionsTotal() > 0){ CheckTrailingstop(GTrigTSLRatioPricebeforeTP,GHighLowShift,GMinTSLDistPoints,HandleATR,GMaximalSLPoints); }*/ } //TRAILING SL void CheckTrailingstop(double TrigTSLRatioPricebeforeTP, int HighLowShift, double MinTSLDistPoints,int ATRHandle, double MaximalSLPoints){ for(int i = PositionsTotal()-1; i >= 0; i--){ string symbol = PositionGetSymbol(i); if(_Symbol == symbol){ ulong PositionTicket = PositionGetInteger(POSITION_TICKET); double PositionOpenprice = PositionGetDouble(POSITION_PRICE_OPEN); double CurrentSL = PositionGetDouble(POSITION_SL); double CurrentTP = PositionGetDouble(POSITION_TP); long PositionType = PositionGetInteger(POSITION_TYPE); string PositionComment = PositionGetString(POSITION_COMMENT); double Price = 0; double LatestHighLow = 0; double NewSL = 0; int LatestHighLowIndex = 0; double MinTSLDistValue = MinTSLDistPoints * _Point; double TPtoOpenpriceDif = MathAbs(PositionOpenprice - CurrentTP); if(PositionType == POSITION_TYPE_BUY && PositionComment == "TSL-Trade"){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); if((CurrentTP != 0 && Price > PositionOpenprice + TPtoOpenpriceDif * TrigTSLRatioPricebeforeTP) || (CurrentTP == 0 && Price > CurrentSL + MinTSLDistValue)){ NewSL = CalcSL(true,HighLowShift,ATRHandle,MaximalSLPoints);//--IMPORTANT NEW SL if(NewSL < CurrentSL){NewSL = 0;} } } else if(PositionType == POSITION_TYPE_SELL && PositionComment == "TSL-Trade"){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); if((CurrentTP != 0 && Price < PositionOpenprice - TPtoOpenpriceDif * TrigTSLRatioPricebeforeTP) || (CurrentTP == 0 && Price < CurrentSL - MinTSLDistValue)){ NewSL = CalcSL(false,HighLowShift,ATRHandle,MaximalSLPoints); //--IMPORTANT NEW SL if(NewSL > CurrentSL){NewSL = 0;} } } if(NewSL != 0){trade.PositionModify(PositionTicket,NewSL,0);} }//END IF CHECK SYMBOL }//END FOR LOOP } //CALC TP double CalcTP(bool BuyTrueSellFalse,double SL, double MaximalTPPoints, double TPtoOneSLRatio){ double TP = 0; double Price = 0; double MaximalTPDist = MaximalTPPoints * _Point; if(BuyTrueSellFalse == true){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double SLPriceDif = MathAbs(SL - Price); double TPPriceDif = SLPriceDif * TPtoOneSLRatio; if(TPPriceDif > MaximalTPDist) {TP = Price + MaximalTPDist;}//IMPORTANT TP else{TP = Price + TPPriceDif;}//IMPORTANT TP }if(BuyTrueSellFalse == false){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); double SLPriceDif = MathAbs(SL - Price); double TPPriceDif = SLPriceDif * TPtoOneSLRatio; if(TPPriceDif > MaximalTPDist) {TP = Price - MaximalTPDist;}//IMPORTANT TP else{TP = Price - TPPriceDif;}//IMPORTANT TP }return TP; } //CALC SL double CalcSL(bool BuyTrueSellFalse, int HighLowShift, int ATRHandle, double MaximalSLPoints){ double Price = 0; double SL = 0; double SLPriceDif = 0; double MaximalSLDist = MaximalSLPoints * _Point; double ATRValues[]; CopyBuffer(ATRHandle,0,0,1,ATRValues); double LatestHighLow = 0; int LatestHighLowIndex = 0; if(BuyTrueSellFalse == true){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); LatestHighLowIndex = iLowest(_Symbol,PERIOD_CURRENT,MODE_LOW,HighLowShift,0); LatestHighLow = iLow(_Symbol,PERIOD_CURRENT,LatestHighLowIndex); if(MathAbs(LatestHighLow - Price) > MaximalSLDist) {SL = Price - MaximalSLDist;}//--IMPORTANT SL else if(MathAbs(LatestHighLow - Price) < ATRValues[0]) {SL = Price - ATRValues[0];}//--IMPORTANT SL }else if(BuyTrueSellFalse == false){ Price = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); LatestHighLowIndex = iHighest(_Symbol,PERIOD_CURRENT,MODE_HIGH,HighLowShift,0); LatestHighLow = iHigh(_Symbol,PERIOD_CURRENT,LatestHighLowIndex); if(MathAbs(LatestHighLow - Price) > MaximalSLDist) {SL = Price + MaximalSLDist;}//--IMPORTANT SL else if(MathAbs(LatestHighLow - Price) < ATRValues[0]) {SL = Price + ATRValues[0];}//--IMPORTANT SL }return SL; } //CHECK FOR TREND IN INDICATOR double CheckINDITrend(datetime Currenttime, int EvaluRangeSec, int INDIHandle, bool Oscillator){ //SETTING ARRAYS AND SIZES UP datetime EvaluStart = Currenttime - EvaluRangeSec; double INDITrendValues[]; CopyBuffer(INDIHandle,0,EvaluStart,Currenttime,INDITrendValues); ArraySetAsSeries(INDITrendValues,true); int INDITrendSize = ArraySize(INDITrendValues); int INDITrendFirstHalf = MathRound(INDITrendSize / 2); int INDITrendSeccondhalf = INDITrendSize - INDITrendFirstHalf; //FIRST HALF AVERAGE CALC double INDITrendFirstSum = 0; for(int i = 0; i < INDITrendFirstHalf; i++){ INDITrendFirstSum = INDITrendFirstSum + INDITrendValues[i];} double INDITrendFirstAv = INDITrendFirstSum / INDITrendFirstHalf; //SECCOND HALF AVERAGE CALC double INDITrendSeccondSum = 0; for(int i = INDITrendFirstHalf; i < INDITrendSize; i++){ INDITrendSeccondSum = INDITrendSeccondSum + INDITrendValues[i];} double INDITrendSeccondAv = INDITrendSeccondSum / INDITrendSeccondhalf; //COMPARING BOTH AVERAGES double INDITrendAvDif = 0; if(Oscillator){INDITrendAvDif = NormalizeDouble((INDITrendFirstAv - INDITrendSeccondAv),0);} else{INDITrendAvDif = NormalizeDouble((INDITrendFirstAv - INDITrendSeccondAv) / _Point,0);} //DEBUGGING /*Print("\nStarttime: ",EvaluStart, "\nCurrenttime: ",Currenttime, "\nRSITrendSize: ",INDITrendSize, "\nRSITrendFirstAv: ",INDITrendFirstAv, "\nRSITrendSeccondAv: ",INDITrendSeccondAv, "\nRSITrendAvDif: ",INDITrendAvDif);*/ if(INDITrendAvDif < 0 || INDITrendAvDif > 0){ return INDITrendAvDif; }else{return 0;} } //CHECK FOR 2 LINE STRIKE DOWN bool Check2LineStrikeDown(double MaxCandleSizeinPoints, double MinCandleSizeinPoints){ double Open1 = iOpen(_Symbol,PERIOD_CURRENT,1); double Close1 = iClose(_Symbol,PERIOD_CURRENT,1); double High1 = iHigh(_Symbol,PERIOD_CURRENT,1); double Open2 = iOpen(_Symbol,PERIOD_CURRENT,2); double Close2 = iClose(_Symbol,PERIOD_CURRENT,2); double High2 = iHigh(_Symbol,PERIOD_CURRENT,2); double Open3 = iOpen(_Symbol,PERIOD_CURRENT,3); double Close3 = iClose(_Symbol,PERIOD_CURRENT,3); if(Open3 < Close3 && Open2 < Close2 && Open1 > Close1 && Close1 < Open2 && MaxCandleSizeinPoints * _Point > MathAbs(Close1 - Open1) && MinCandleSizeinPoints * _Point < MathAbs(Close1 - Open1) && MathAbs(Open1 - Close2) < 5 * _Point){ return true;} else{return false;} } //CHECK FOR 2 LINE STRIKE UP double Check2LineStrikeUp(double MaxCandleSizeinPoints, double MinCandleSizeinPoints){ double Open1 = iOpen(_Symbol,PERIOD_CURRENT,1); double Close1 = iClose(_Symbol,PERIOD_CURRENT,1); double Low1 = iLow(_Symbol,PERIOD_CURRENT,1); double Open2 = iOpen(_Symbol,PERIOD_CURRENT,2); double Close2 = iClose(_Symbol,PERIOD_CURRENT,2); double Low2 = iLow(_Symbol,PERIOD_CURRENT,2); double Open3 = iOpen(_Symbol,PERIOD_CURRENT,3); double Close3 = iClose(_Symbol,PERIOD_CURRENT,3); if(Open3 > Close3 && Open2 > Close2 && Open1 < Close1 && Close1 > Open2 && MaxCandleSizeinPoints * _Point > MathAbs(Close1 - Open1) && MinCandleSizeinPoints * _Point < MathAbs(Close1 - Open1) && MathAbs(Open1 - Close2) < 5 * _Point){ return true;} else{return false;} } //DYNAMIC LOT CALCULATION double CalcLots(double riskPercent, double SLDistance){ double ticksize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE); double tickvalue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE); double Lotstep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); if(ticksize == 0 || tickvalue == 0 || Lotstep == 0){ Print(__FUNCTION__,"Lotsize cannot be calculated"); return 0;} double riskMoney = AccountInfoDouble(ACCOUNT_BALANCE) * riskPercent /100; double MoneyperLotstep = (SLDistance / ticksize) * tickvalue * Lotstep; if(MoneyperLotstep == 0){ Print(__FUNCTION__,"Lotsize cannot be calculated"); return 0;} double lots = MathFloor(riskMoney / MoneyperLotstep) * Lotstep; return lots; }