#property copyright "Copyright 2023, M & Q Investment Group" #property link "https://www.mql5.com" #property version "1.00" #include CTrade trade; //-------------------------------------------OVEROPTIMIZED VERSION 5 AFTER 2. TESTING ------------- //Added Dynamic Lotsizing //Extra Feature - Determine Trend of indicator with function and not extra indicator //made the code lean ->better prioritizing with conditions input double TrigPDif = 0.00005; input double DesiredProfitPerc = 20; input int ExpiryTime = 120; input double SLtoTPRatio = 1; input double RuleMinimumTPSLValue = 0.0001; input double PufferDistance = 0.0001; input double WhiteYellowProtRange = 0.00001; input bool SWhiteProtection = true; input double StaticLots = 1.0; input bool DynamicLotsCalc = false; input bool CondCandleLowtrueClosefalse = false; input bool CondCountCandle1true2false = false; //AUSSTEHEND input double TPSLFactor = 1.0; input string Opentime = "04:30:00"; input string CloseTime = "23:45:"; //long TickVolumes[]; double accountbalancebeginning; double accountprofit; int HandleYellAMA; int HandleRedAMA; int OnInit(){ HandleYellAMA = iAMA (_Symbol,_Period,2,5,1,0,PRICE_CLOSE); HandleRedAMA = iAMA (_Symbol,_Period,5,2,30,0,PRICE_CLOSE); accountbalancebeginning = AccountInfoDouble(ACCOUNT_BALANCE); //OrderinAction = false; return(INIT_SUCCEEDED); } void OnTick(){ //DETERMINING TIMEFRAME datetime opentimenow = StringToTime(Opentime); datetime closetimenow = StringToTime(CloseTime); datetime currenttime = TimeCurrent(); if(currenttime > opentimenow && currenttime < closetimenow && PositionsTotal() == 0 && OrdersTotal() == 0){ double TrendRed = CheckINDITrend(currenttime,INDIEvaluRangeSec,HandleRedAMA,false); double TrendYellow = CheckINDITrend(currenttime,INDIEvaluRangeSec,HandleRedAMA,false); if(TrendYellow >= MinimalDowntrendYell && MaximalUptrendYellRed <= TrendYellow && MaximalUptrendYellRed <= TrendRed){ //GET YELLWOW AMA VALUES double YellAMAPriceArray[]; ArraySetAsSeries(YellAMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(HandleYellAMA,0,0,10,YellAMAPriceArray); double YellAMACurrentValue = NormalizeDouble(YellAMAPriceArray[0],6); //GET RED AMA VALUES double RedAMAPriceArray[]; ArraySetAsSeries(RedAMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(HandleRedAMA,0,0,10,RedAMAPriceArray); double RedAMACurrentValue = NormalizeDouble(RedAMAPriceArray[0],6); //SET THE ORDER double bid0 = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); double PufferPrice = RedAMACurrentValue + PufferDistance; double TrigP = bid0 - TrigPDif; double InvalidStopProhibitorline = RuleMinimumTPSLValue + PufferDistance + RedAMACurrentValue; if( YellAMACurrentValue > bid0 && YellAMACurrentValue > PufferPrice && //SWhiteAMACurrentValue > WhiteAMACurrentValue && TrigP > InvalidStopProhibitorline){ double iLow1 = iLow(_Symbol,PERIOD_CURRENT,1); double iLow2 = iLow(_Symbol,PERIOD_CURRENT,2); double iClose1 = iClose(_Symbol,PERIOD_CURRENT,1); double iClose2 = iClose(_Symbol,PERIOD_CURRENT,2); double TP = RedAMACurrentValue; //SL wurde in Googleversion und V4 falsch berechnet (mit dem Bid0 Preis). Anpassung zu TriggerP vorgenommen double SL = TrigP + (TrigP - RedAMACurrentValue) * SLtoTPRatio; datetime OrderExpTime = TimeCurrent() + ExpiryTime; //if(SWhiteProtection == false){SWhiteAMACurrentValue = 5;} //MODELLING OF TRADING CONDITIONS FOR OPTIMIZER if(CondCandleLowtrueClosefalse == false){iLow1 = 100; iLow2 = 100;} if(CondCandleLowtrueClosefalse == true){iClose1 = 100; iClose2 = 100;} if(CondCountCandle1true2false == true){iClose2 = 100; iLow2 = 100;} if( iLow1 > RedAMACurrentValue + PufferDistance && iLow2 > RedAMACurrentValue + PufferDistance && iClose1 > RedAMACurrentValue + PufferDistance && iClose2 > RedAMACurrentValue + PufferDistance){ //CALC LOTS double Lots = 0.01; if(DynamicLotsCalc){ double SLDistance = SL - TrigP; Lots = CalcLots(DesiredProfitPerc,SLDistance); }else{Lots = StaticLots;} trade.SellStop(Lots,TrigP,_Symbol,SL,TP,ORDER_TIME_SPECIFIED,OrderExpTime); /*Print(//"\nPinkAMA-Value ",PinkAMACurrentValue, "\nYellAMA-Value ",YellAMACurrentValue, "\nRedAMA-Value ",RedAMACurrentValue, "\niLow 1: ",iLow1, "\niLow2",iLow2, "\nBid ",bid0);*/ } } }//END IF TREND }//END TIMEFRAME }//END ONTICK 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);*/ } double OnTester(){ double Lostrades = TesterStatistics(STAT_LOSS_TRADES); double Wintrades = TesterStatistics(STAT_PROFIT_TRADES); double AllWinRatio; if(Lostrades + Wintrades > 0){ AllWinRatio = NormalizeDouble(Wintrades / (Wintrades + Lostrades),2); }else{AllWinRatio = 0;} return(AllWinRatio); } //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; } //CHECK FOR TREND IN INDICATOR input int INDIEvaluRangeMin = 4; input int MaximalUptrendYellRed = 10; input int MinimalDowntrendYell = 5; int INDIEvaluRangeSec = INDIEvaluRangeMin * 60; 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;} }