195 lines
8.5 KiB
MQL5
195 lines
8.5 KiB
MQL5
|
#property copyright "Copyright 2023, M & Q Investment Group"
|
||
|
#property link "https://www.mql5.com"
|
||
|
#property version "1.00"
|
||
|
#include <trade/trade.mqh>
|
||
|
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;}
|
||
|
}
|