216 lines
No EOL
20 KiB
MQL5
216 lines
No EOL
20 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;
|
|
|
|
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 GMaxPriceBufferrange = 30;
|
|
input double GExtraOverEngulfingPoints = 20;
|
|
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(){
|
|
HandleATR = iATR(_Symbol,PERIOD_CURRENT,14);
|
|
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 GCurrenttime = TimeCurrent();
|
|
int CandleNumber = Bars(_Symbol,_Period);
|
|
if(CheckfornewCandle(CandleNumber,GCurrenttime)){
|
|
int EngulfingValue = CheckEngulfingPatternUp1Net0Down2(GExtraOverEngulfingPoints,GMaxPriceBufferrange);
|
|
if(EngulfingValue != 0){
|
|
Print("Engulfing Pattern ---",EngulfingValue,
|
|
"Currenttime: ",GCurrenttime,
|
|
"\nClose1: ",iClose(_Symbol,PERIOD_CURRENT,1),
|
|
"\nAsk: ",SymbolInfoDouble(_Symbol,SYMBOL_ASK),
|
|
"\nBid: ",SymbolInfoDouble(_Symbol,SYMBOL_BID));
|
|
}
|
|
}
|
|
}
|
|
//CHECK FOR NEW CANDLE
|
|
bool CheckfornewCandle (int CandleNumber, datetime Currenttime){
|
|
static int LastCandleNumber;
|
|
bool IsNewCandle= false;
|
|
if (CandleNumber>LastCandleNumber){
|
|
IsNewCandle = true;
|
|
LastCandleNumber = CandleNumber;
|
|
Print("------New Candle----- Time: ",Currenttime);
|
|
}
|
|
return IsNewCandle;
|
|
}
|
|
//CHECK FOR ENGULFING PATTERN
|
|
int CheckEngulfingPatternUp1Net0Down2(double ExtraOverEngulfingPoints, int MaxPriceBufferrange){
|
|
int CheckEngulfingPatternUp1Net0Down2Value = 0;
|
|
for(int i = 2; i < MaxPriceBufferrange; i++){
|
|
int iSize = i;
|
|
double PriceCloseValues[];
|
|
CopyClose(_Symbol,PERIOD_CURRENT,0,i,PriceCloseValues);
|
|
ArraySetAsSeries(PriceCloseValues,true);
|
|
double PriceOpenValues[];
|
|
CopyOpen(_Symbol,PERIOD_CURRENT,0,i,PriceOpenValues);
|
|
ArraySetAsSeries(PriceOpenValues,true);
|
|
double PriceLowValues[];
|
|
CopyLow(_Symbol,PERIOD_CURRENT,0,i,PriceLowValues);
|
|
ArraySetAsSeries(PriceLowValues,true);
|
|
double PriceHighValues[];
|
|
CopyHigh(_Symbol,PERIOD_CURRENT,0,i,PriceHighValues);
|
|
ArraySetAsSeries(PriceHighValues,true);
|
|
int CandleUp1Neut0Down2[];
|
|
ArrayResize(CandleUp1Neut0Down2,iSize);
|
|
for(int k = 0; k < iSize; k++){
|
|
if(PriceOpenValues[k] < PriceCloseValues[k]){CandleUp1Neut0Down2[k] = 1;}
|
|
else if(PriceOpenValues[k] > PriceCloseValues[k]){CandleUp1Neut0Down2[k] = 2;}
|
|
else if(PriceOpenValues[k] == PriceCloseValues[k]){CandleUp1Neut0Down2[k] = 0;}
|
|
}
|
|
//fängt bei Null an,da bei einstieg in kommendes if derStreak sozusagen 1 ist und Indextechnisch 0 sein muss
|
|
//UPTREND
|
|
int Streakcounter = 0;
|
|
if(CandleUp1Neut0Down2[0] == 1){
|
|
int j = 1;
|
|
int TrenEndIndex = 0;
|
|
for(j; j < iSize; j++){
|
|
if(CandleUp1Neut0Down2[j] == 1){Streakcounter = Streakcounter + 1;}
|
|
else if(CandleUp1Neut0Down2[j] == 2){TrenEndIndex = j; j = iSize;}
|
|
else if(CandleUp1Neut0Down2[j] == 0){j = iSize;}
|
|
}if(TrenEndIndex > 0){
|
|
if(PriceHighValues[TrenEndIndex] < SymbolInfoDouble(_Symbol,SYMBOL_ASK) + ExtraOverEngulfingPoints * _Point){
|
|
CheckEngulfingPatternUp1Net0Down2Value = 1; break;
|
|
}else if(TrenEndIndex == 0){break;}
|
|
}
|
|
}
|
|
//DOWNTREND
|
|
Streakcounter = 0;
|
|
if(CandleUp1Neut0Down2[0] == 2){
|
|
int j = 1;
|
|
int TrenEndIndex = 0;
|
|
for(j; j < iSize; j++){
|
|
if(CandleUp1Neut0Down2[j] == 2){Streakcounter = Streakcounter + 1;}
|
|
else if(CandleUp1Neut0Down2[j] == 1){TrenEndIndex = j; j = iSize;}
|
|
else if(CandleUp1Neut0Down2[j] == 0){j = iSize;}
|
|
}if(TrenEndIndex > 0){
|
|
if(PriceHighValues[TrenEndIndex] < SymbolInfoDouble(_Symbol,SYMBOL_BID) + ExtraOverEngulfingPoints * _Point){
|
|
CheckEngulfingPatternUp1Net0Down2Value = 2; break;
|
|
}else if(TrenEndIndex == 0){break;}
|
|
}
|
|
}
|
|
}
|
|
return CheckEngulfingPatternUp1Net0Down2Value;
|
|
}
|
|
//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 < 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,HighLowShift,ATRHandle,MaximalSLPoints); //--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
|
|
}
|
|
//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;
|
|
} |