MnQInvestmentDevelopment/MnQInvestment/02_EigeneScalpingprojekte/TrendlineSurferV2.mq5
super.admin cff55d2704 convert
2025-05-30 15:08:44 +02:00

313 lines
No EOL
14 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 double IndiTrendMiniValue = 20;
input double OsciTrendMiniValue = 10;
double MinTrendValue = 20;
input int RSIOverboughtlevel = 70;
input int RSIOversoldlevel = 30;
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 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 MA200Trend = CheckINDITrend(Currenttime,INDIEvaluRangeSec,HandleMA200,false);
double RSICurrentValue[];
CopyBuffer(HandleRSI,0,0,1,RSICurrentValue);
double MA200CurrentValue[];
CopyBuffer(HandleMA200,0,0,1,MA200CurrentValue);
Comment("\n RSITrend: ",RSITrend,
"\n MA21Trend: ",MA21Trend,
"\n MA50Trend: ",MA50Trend);
if(PositionsTotal() == 0 && OrdersTotal() == 0 && Currenttime > Tradecooldown){
double IndiTrendMiniValueNeg = IndiTrendMiniValue * - 1;
double OsciTrendMiniValueNeg = OsciTrendMiniValue * -1;
double SL = 0;
double TP = 0;
double Lots = 0;
double Price = 0;
double RiskSplitPerc = RiskPerc / 3; // --- IMPORTANT LOTCALC
string TradeComment ="RSITrend: "+ DoubleToString(RSITrend,0) +
" MA21Trend: " + DoubleToString(MA21Trend,0) +
" MA50Trend: " + DoubleToString(MA50Trend,0);
//SELLTREND
if(RSITrend < OsciTrendMiniValueNeg
&& 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 > OsciTrendMiniValue
&& 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;
Print("\nRSITrend: ",RSITrend,
"\nRSICurrentValue[0]: ",RSICurrentValue[0],
"\nMA21Trend: ",MA21Trend,
"\nMA50Trend: ",MA50Trend,
"\nMA200Trend: ",MA200Trend,
"\nSL: ",SL,
"\nTP: ",TP,
"\nLots: ",Lots,
"\nPrice: ",Price);
}
}
if(PositionsTotal() > 0){
CheckTrailingstop(GTrigTSLRatioPricebeforeTP,GHighLowShift,GMinTSLDistPoints,HandleATR,GMaximalSLPoints);
}
double accountequity = AccountInfoDouble(ACCOUNT_EQUITY);
accountprofit = accountequity - accountbalancebeginning;
accountprofit = NormalizeDouble(accountprofit,2);
Comment("\nCurrenttime: ",TimeCurrent(),
"\nProfit: ",accountprofit,
"\nEquity: ",accountequity,
"\nRSITrend: ",RSITrend,
"\nRSICurrentValue[0]: ",RSICurrentValue[0],
"\nMA21Trend: ",MA21Trend,
"\nMA50Trend: ",MA50Trend,
"\nMA200Trend: ",MA200Trend);
}
//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
input double GMaximalTPPoints = 100;
input double GTPtoOneSLRatio = 1;
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
input int GHighLowShift = 10;
input double GMaximalSLPoints = 100;
int HandleATR;
//HandleATR = iATR(_Symbol,PERIOD_CURRENT,14);
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
input int INDIEvaluRangeMin = 100;
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;}
}
//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;
}