#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 input double DesiredProfitPerc = 1; input double RatioSLtoTP = 0.5; input double PufferDistance = 0.0001; input double RuleMinimumTPSLValue = 0.00015; //input double TrigPDist = 0.00015; input int ExpiryTime = 600; input double RisingProtDiff = 0.0002; //input double RisingProtRange = 0.00001; input double MinimalTP = 0.0003; input int TradecooldownSec = 300; datetime Tradecooldown; //TrailingSL input bool TrailingSLActive = true; input double TrailingSLSteps = 0.00005; input double TrailingSLActivation = 0.0001; input double TrailingSLDist1 = 0.00025; input double TrailingSLDist2 = 0.00015; input double TrailingSLDist2Activation = 0.0001; double LiveTP; //double NewSL; input string Opentime = "04:30:00"; input string CloseTime = "23:45:"; input double StaticLots = 1.0; input bool DynamicLotsCalc = false; double accountbalancebeginning; double accountprofit; double Lostrades = 0; double Wintrades = 0; double AllWinRatio = 0; int OnInit(){ HandleATR = iATR(_Symbol,PERIOD_CURRENT,14); 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){ //GET YELLWOW AMA VALUES double YellAMAPriceArray[]; int YellAMADefinition = iAMA (_Symbol,_Period,2,5,1,0,PRICE_CLOSE); ArraySetAsSeries(YellAMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(YellAMADefinition,0,0,10,YellAMAPriceArray); double YellAMACurrentValue = NormalizeDouble(YellAMAPriceArray[0],6); //GET WHITE AMA VALUES double WhiteAMAPriceArray[]; int WhiteAMADefinition = iAMA (_Symbol,_Period,2,5,1,1,PRICE_CLOSE); ArraySetAsSeries(WhiteAMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(WhiteAMADefinition,0,0,10,WhiteAMAPriceArray); double WhiteAMACurrentValue = NormalizeDouble(WhiteAMAPriceArray[0],6); //GET RED AMA VALUES double RedAMAPriceArray[]; int RedAMADefinition = iAMA (_Symbol,_Period,5,2,30,0,PRICE_CLOSE); ArraySetAsSeries(RedAMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(RedAMADefinition,0,0,10,RedAMAPriceArray); double RedAMACurrentValue = NormalizeDouble(RedAMAPriceArray[0],6); //GET ORANGE AMA VALUES double OrangeAMAPriceArray[]; int OrangeAMADefinition = iAMA (_Symbol,_Period,5,2,30,1,PRICE_CLOSE); ArraySetAsSeries(OrangeAMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(OrangeAMADefinition,0,0,10,OrangeAMAPriceArray); double OrangeAMACurrentValue = NormalizeDouble(OrangeAMAPriceArray[0],6); //GET ORANGE2 AMA VALUES double Orange2AMAPriceArray[]; int Orange2AMADefinition = iAMA (_Symbol,_Period,5,2,30,2,PRICE_CLOSE); ArraySetAsSeries(Orange2AMAPriceArray,true); //AMA DEF, one line, current candle, 3 candles, store result CopyBuffer(Orange2AMADefinition,0,0,10,Orange2AMAPriceArray); double Orange2AMACurrentValue = NormalizeDouble(Orange2AMAPriceArray[0],6); //SET THE ORDER double bid0 = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); // Low1 > PufferPrice1 double PufferPrice1 = 0; if(OrangeAMACurrentValue + PufferDistance < WhiteAMACurrentValue + PufferDistance){ PufferPrice1 = WhiteAMACurrentValue + PufferDistance; }else{PufferPrice1 = OrangeAMACurrentValue + PufferDistance;} //Close1 > bid0 > Pufferprice0; TP, SL double Low1 = iLow(_Symbol,PERIOD_CURRENT,1); double Close1 = iClose(_Symbol,PERIOD_CURRENT,1); double Open1 = iOpen(_Symbol,PERIOD_CURRENT,1); double Open2 = iOpen(_Symbol,PERIOD_CURRENT,2); double Close2 = iClose(_Symbol,PERIOD_CURRENT,2); double Open3 = iOpen(_Symbol,PERIOD_CURRENT,3); double Close3 = iClose(_Symbol,PERIOD_CURRENT,3); double Open4 = iOpen(_Symbol,PERIOD_CURRENT,4); double Close4 = iClose(_Symbol,PERIOD_CURRENT,4); double Pufferprice0 = 0; //double TrigP = bid0 - TrigPDist; double TP = 0; double SL = 0; double AboveIndCurrentValue = 0; if(RedAMACurrentValue + PufferDistance < YellAMACurrentValue + PufferDistance){ Pufferprice0 = YellAMACurrentValue + PufferDistance; TP = RedAMACurrentValue; //TP = YellAMACurrentValue; SL = bid0 + ((bid0 - TP) * RatioSLtoTP); //SL = TrigP + ((TrigP - TP) * RatioSLtoTP); AboveIndCurrentValue = YellAMACurrentValue; }else{ Pufferprice0 = RedAMACurrentValue + PufferDistance; TP = YellAMACurrentValue; //TP = RedAMACurrentValue; SL = bid0 + ((bid0 - TP) * RatioSLtoTP); //SL = TrigP + ((TrigP - TP) * RatioSLtoTP); AboveIndCurrentValue = RedAMACurrentValue; } //LOOK FOR INVALID STOPS - SL MIN VALUE ABGLEICH if(//TrigP > SL - RuleMinimumTPSLValue){ bid0 > SL - RuleMinimumTPSLValue){ //double InvalidRange = TrigP + RuleMinimumTPSLValue - SL; double InvalidRange = bid0 + RuleMinimumTPSLValue - SL; SL = SL + InvalidRange; TP = TP - (InvalidRange * (1 / RatioSLtoTP)); } //CHECK FOR RISING MARKET double OrangeO2Diff = MathAbs(Orange2AMACurrentValue - OrangeAMACurrentValue); bool Last2to4Rise = false; if(Open2 <= Close2 && Open3 <= Close3 && Open4 <= Close4){Last2to4Rise = true;} //OPEN TRADE if(Low1 > PufferPrice1 && Open1 > bid0 && bid0 > Pufferprice0 && Close1 < Open1 && OrangeO2Diff < RisingProtDiff && Last2to4Rise == false && //Close2 > AboveIndCurrentValue && Open2 > AboveIndCurrentValue && Close1 - MinimalTP > AboveIndCurrentValue && //OrangeAMACurrentValue - RisingProtRange > RedAMACurrentValue && //WhiteAMACurrentValue > YellAMACurrentValue && YellAMACurrentValue != 0 && WhiteAMACurrentValue != 0 && RedAMACurrentValue != 0 && OrangeAMACurrentValue != 0 && currenttime > Tradecooldown && PositionsTotal() == 0 && OrdersTotal() == 0){ //CALC LOTS double Lots = 0; if(DynamicLotsCalc){ //CHANGE BETWEEN BASE OF CALCULATION OF LOTS //double SLDistance = SL - bid0; double TPDistance = bid0 - TP; Lots = CalcLots(DesiredProfitPerc,TPDistance); }else{Lots = StaticLots;} datetime OrderExpTime = TimeCurrent() + ExpiryTime; //trade.SellStop(Lots,TrigP,_Symbol,SL,TP,ORDER_TIME_SPECIFIED,OrderExpTime); trade.Sell(Lots, _Symbol, bid0, SL, TP); LiveTP = TP; Tradecooldown = currenttime + TradecooldownSec; Print(//"\nPinkAMA-Value ",PinkAMACurrentValue, "\nYellAMA-Value ",YellAMACurrentValue, "\nWhiteAMA-Value ",WhiteAMACurrentValue, "\nRedAMA-Value ",RedAMACurrentValue, "\nOrangeAMA-Value ",OrangeAMACurrentValue, "\niLow 1: ",Low1, "\niOpen1",Open1, "\nBid ",bid0); } //TRAILING SL if(PositionsTotal()> 0 && TrailingSLActive){CheckTrailingstop(HandleATR);} // DISPLAY OF VALUES ON CHART double accountequity = AccountInfoDouble(ACCOUNT_EQUITY); accountprofit = accountequity - accountbalancebeginning; accountprofit = NormalizeDouble(accountprofit,2); Comment("\nCurrenttime: ",TimeCurrent(), "\nProfit: ",accountprofit, "\nEquity: ",accountequity, "\nYellAMA-Value ",YellAMACurrentValue, "\nWhiteAMA-Value ",WhiteAMACurrentValue, "\nRedAMA-Value ",RedAMACurrentValue, "\nOrangeAMA-Value ",OrangeAMACurrentValue, "\niLow 1: ",Low1, "\niOpen1",Open1, "\nBid ",bid0); }//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(){ Lostrades = TesterStatistics(STAT_LOSS_TRADES); Wintrades = TesterStatistics(STAT_PROFIT_TRADES); if(Lostrades + Wintrades > 0){ AllWinRatio = NormalizeDouble(Wintrades / (Wintrades + Lostrades),2); }else{AllWinRatio = 0;} return(AllWinRatio); } //CALC SL input int HighLowShift = 10; input double MaximalSLPoints = 100; int HandleATR; //HandleATR = iATR(_Symbol,PERIOD_CURRENT,14); double CalcSL(bool BuyTrueSellFalse, int ATRHandle){ 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; } //TRAILING SL--NEEDS CALC SL input double TrigTSLRatioPricebeforeTP = 0.5; input int MinTSLDistPoints = 50; void CheckTrailingstop(int ATRHandle){ 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,ATRHandle);//--IMPORTANT NEW SL if(NewSL < CurrentSL || NewSL < PositionOpenprice){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,ATRHandle); //--IMPORTANT NEW SL if(NewSL > CurrentSL || NewSL > PositionOpenprice){NewSL = 0;} } } if(NewSL != 0){trade.PositionModify(PositionTicket,NewSL,0);} }//END IF CHECK SYMBOL }//END FOR LOOP } //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; }