334 lines
14 KiB
MQL5
334 lines
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;
|
|
//-------------------------------------------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;
|
|
}
|
|
|