PivotPullback/PivotPullback.mq5
super.admin 7fe2ccfecb convert
2025-05-30 16:16:29 +02:00

602 lines
22 KiB
MQL5

//+------------------------------------------------------------------+
//| PivotPullback.mq5 |
//| Copyright 2018, Benjamin Pillet |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, Benjamin Pillet"
#property link ""
#define VERSION "1.10"
#property version VERSION
//#include <dataToFile.mqh>
#include "JPBP.mqh"
enum SLstrat
{
SL_FixPoint,//fix amount of points
SL_SR1,//S1/R1
SL_SR2,//S2/R2
SL_SR3,//S3/R3
SL_TPratio//ratio of take profit
};
enum TPstrat
{
TP_SLratio,//ratio of stop loss
TP_SR1,//S1/R1 or closest pivot line
TP_SR2,//S2/R2 or closest pivot line
TP_SR3//S3/R3 or closest pivot line
};
enum Exit
{
NoExit,//no other exit than TP/SL
InstantEMA1EMA2cross,//instantly exit if EMA1 cross EMA2
InstantEMA1EMA3cross,//instantly exit if EMA1 cross EMA3
DelayEMA1EMA2cross,//exit if EMA1 crossed EMA2 in previous bar
DelayEMA1EMA3cross//exit if EMA1 crossed EMA3 in previous bar
};
//--- main input parameters
input double Lots = 0; //Lots, 0=compound
//--- Entry input parameters
input int MaxSpread = 0; //check spread and set a maximum, 0 = no check
input bool OnePos = false; //open only one position
input bool NotOneMonday = false; // do not open on Monday
input bool CheckPrevPivot = true; //check previous central pivot
input bool SR2Check = false;// do not open if price above/below R2/S2
input bool CheckOnlyLowHigh = false; //delay entry
input bool CheckEMAsDirection = false; //check the slopes of EMAs
input int Ema3Offset = 0; //EMA3 offset
input int DiffEMA1EMA2 = 0;//distance between EMA1 and EMA2
input int DiffEMA2EMA3 = 0;//distance between EMA2 and EMA3
//--- exit input parameters
input SLstrat SLsetup = SL_SR1;//stop loss policy
input int SLpoints = 300;
input TPstrat TPsetup = TP_SR1;//take profit policy
input TPstrat SafeSetup = TP_SR1;//safe policy
input TPstrat TrailingSetup = TP_SLratio;//trailing policy
input Exit ExitSetup = NoExit; //exit policy
//--- input parameters for indicators
input int Ema1Period = 4;//period of EMA1
input int Ema2Period = 15;//period of EMA2
input int Ema3Period = 30;//period of EMA3
input color Ema1Colour = clrRed;//colour of EMA1
input color Ema2Colour = clrYellow;//colour of EMA2
input color Ema3Colour = clrLightGray;//colour of EMA3
//--- global variables
string pivotPath = "Shared Projects\\PivotPullback\\PivotPoint.ex5";
string colourMAPath = "Shared Projects\\PivotPullback\\ColourMA.ex5";
datetime expDate;
ulong currentOrderTickets[2];
bool orderStatus[2];
datetime baseStartTime;
double fprice;
double fsl;
double ftp;
double fvolume;
double prevBid;
double prevPivot;
//---Indicator handle
int ema1Handle;
int ema2Handle;
int ema3Handle;
int pivotHandle;
//---Indicator buffer
double ema1Value[];
double ema2Value[];
double ema3Value[];
double pivotValue[];
double R1[];
double R2[];
double R3[];
double S1[];
double S2[];
double S3[];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- set indicators
ema1Handle = iCustom(_Symbol,TimeFrame,colourMAPath,TimeFrame,Ema1Period,MODE_EMA,Ema1Colour);
ema2Handle = iCustom(_Symbol,TimeFrame,colourMAPath,TimeFrame,Ema2Period,MODE_EMA,Ema2Colour);
ema3Handle = iCustom(_Symbol,TimeFrame,colourMAPath,TimeFrame,Ema3Period,MODE_EMA,Ema3Colour);
//ema1Handle = iMA(_Symbol,TimeFrame,Ema1Period,0,MODE_EMA,PRICE_CLOSE);
//ema2Handle = iMA(_Symbol,TimeFrame,Ema2Period,0,MODE_EMA,PRICE_CLOSE);
//ema3Handle = iMA(_Symbol,TimeFrame,Ema3Period,0,MODE_EMA,PRICE_CLOSE);
pivotHandle = iCustom(_Symbol,TimeFrame,pivotPath);
//---Set array as series
ArraySetAsSeries(ema1Value,true);
ArraySetAsSeries(ema2Value,true);
ArraySetAsSeries(ema3Value,true);
ArraySetAsSeries(pivotValue,true);
ArraySetAsSeries(R1,true);
ArraySetAsSeries(S1,true);
ArraySetAsSeries(R2,true);
ArraySetAsSeries(S2,true);
ArraySetAsSeries(R3,true);
ArraySetAsSeries(S3,true);
//--- set variables
setVariables();
trade.SetExpertMagicNumber(MagicNumber);
arraySize = 0;
orderPlaced[0] = false;
orderPlaced[1] = false;
positionTotal = 0;
//--- recovery system
//set order placed and base start time
for(int i=0; i < OrdersTotal(); i++){
ulong oTicket = OrderGetTicket(i);
if(OrderSelect(oTicket)){
if(OrderGetInteger(ORDER_MAGIC) == MagicNumber && OrderGetString(ORDER_SYMBOL) == _Symbol){
baseStartTime = OrderGetInteger(ORDER_TIME_SETUP);
timeSet = true;
orderPlaced[0] = true;
orderPlaced[1] = true;
if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP){
currentOrderTickets[0] = oTicket;
}
else if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP){
currentOrderTickets[1] = oTicket;
}
}
}
}
//put position back into the system
for(int i=0; i< PositionsTotal(); i++){
if(PositionSelectByTicket(PositionGetTicket(i))){
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol){
positionTotal = positionTotal + 1;
AddPosition();
orderPlaced[0] = true;
orderPlaced[1] = true;
}
}
}
prevPositionTotal = positionTotal;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---release indicators
IndicatorRelease(ema1Handle);
IndicatorRelease(ema2Handle);
IndicatorRelease(ema3Handle);
IndicatorRelease(pivotHandle);
}
//+------------------------------------------------------------------+
//| Custom functions |
//+------------------------------------------------------------------+
double SetBuyProfitLimit(TPstrat policy){
double p=0;
switch(policy){
case TP_SLratio:
p = ask + (bid-fsl)*TpSlRatio;
break;
case TP_SR1:
if(ask < R3[0]){
p = R3[0];
if(ask < R2[0]){
p = R2[0];
if(ask < R1[0]){
p = R1[0];
}
}
}
break;
case TP_SR2:
if(ask < R3[0]){
p = R3[0];
if(ask < R2[0]){
p = R2[0];
}
}
break;
case TP_SR3:
if(ask < R3[0]){
p = R3[0];
}
break;
}
return p;
}
double SetSellProfitLimit(TPstrat policy){
double p=0;
switch(policy){
case TP_SLratio:
p = bid - (fsl - ask)*TpSlRatio;
break;
case TP_SR1:
if(bid > S3[0]){
p = S3[0];
if(bid > S2[0]){
p = S2[0];
if(bid > S1[0]){
p = S1[0];
}
}
}
break;
case TP_SR2:
if(bid > S3[0]){
p = S3[0];
if(bid > S2[0]){
p = S2[0];
}
}
break;
case TP_SR3:
if(bid > S3[0]){
p = S3[0];
}
break;
}
return p;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---Acquires indicators informations
CopyBuffer(ema1Handle,0,0,3,ema1Value);
CopyBuffer(ema2Handle,0,0,3,ema2Value);
CopyBuffer(ema3Handle,0,0,3,ema3Value);
CopyBuffer(pivotHandle,0,0,3,pivotValue);
CopyBuffer(pivotHandle,1,0,3,R1);
CopyBuffer(pivotHandle,2,0,3,R2);
CopyBuffer(pivotHandle,3,0,3,R3);
CopyBuffer(pivotHandle,4,0,3,S1);
CopyBuffer(pivotHandle,5,0,3,S2);
CopyBuffer(pivotHandle,6,0,3,S3);
if(today.day_of_year != prevDay){
prevDay = today.day_of_year;
prevPivot = pivotValue[1];
}
//--- get market info
refreshVariables();
//--- count the number of position opened by this EA and add new position to trailing system
positionTotal = 0;
for(int i=0; i< PositionsTotal(); i++){
posTicket = PositionGetTicket(i);
if(PositionSelectByTicket(posTicket)){
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol){
positionTotal = positionTotal + 1;
//set parameters if a new position was opened
if(positionTotal > prevPositionTotal && (SafeMode || TrailingMode)){
AddPosition();
//adjust safe and trailing if not default policy
if(SafeSetup != TP_SLratio && SafeMode){
if(positionType == POSITION_TYPE_BUY){
safeActivationPrice[arrayIndex] = SetBuyProfitLimit(SafeSetup);
safeSL[arrayIndex] = NormalisePrice(positionOpenPrice + (positionOpenPrice-positionSL)*SafeSlRatio);
}
else if(positionType==POSITION_TYPE_SELL){
safeActivationPrice[arrayIndex] = SetSellProfitLimit(SafeSetup);
safeSL[arrayIndex] = NormalisePrice(positionOpenPrice - (positionSL-positionOpenPrice)*SafeSlRatio);
if(safeSL[arrayIndex]<0)safeSL[arrayIndex] = 0;
}
if(DrawLines){
ObjectMove(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),0,0,safeActivationPrice[arrayIndex]);
}
}
if(TrailingSetup != TP_SLratio && TrailingMode){
if(positionType == POSITION_TYPE_BUY){
trailingActivationPrice[arrayIndex] = SetBuyProfitLimit(TrailingSetup);
trailingDistance[arrayIndex] = (trailingActivationPrice[arrayIndex]-positionOpenPrice)*(TrailingDistance/100);
}
else if(positionType==POSITION_TYPE_SELL){
trailingActivationPrice[arrayIndex] = SetSellProfitLimit(TrailingSetup);
trailingDistance[arrayIndex] = (positionOpenPrice - trailingActivationPrice[arrayIndex])*(TrailingDistance/100);
}
if(DrawLines){
ObjectMove(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),0,0,trailingActivationPrice[arrayIndex]);
}
}
}
}
}
}
//--- remove lines if a position was closed
if(positionTotal < prevPositionTotal){
HistorySelect(0,TimeCurrent());
for(int i=0; i<prevPositionTotal-positionTotal; i++){
histDealTicket = HistoryDealGetTicket((HistoryDealsTotal()-1)-i);
ObjectDelete(0,"Safe Activation #"+IntegerToString(HistoryDealGetInteger(histDealTicket,DEAL_POSITION_ID)));
ObjectDelete(0,"Trailing Activation #"+IntegerToString(HistoryDealGetInteger(histDealTicket,DEAL_POSITION_ID)));
}
}
prevPositionTotal = positionTotal;
//--- Define conditions for instant execution
//general conditions
bool onlyOneTrade;
if(OnePos) onlyOneTrade = positionTotal == 0; else onlyOneTrade = true;
bool notMonday;
if(NotOneMonday){
notMonday = today.day_of_week != 1;
}
else{
notMonday = true;
}
bool notSameBar = lastOpen != bar[0].open;
bool spreadOK;
if(MaxSpread != 0){
spreadOK = ask - bid < MaxSpread*_Point;
}
else{
spreadOK = true;
}
//buy conditions
bool buyCondition2 = ema1Value[0] > pivotValue[0] && ema2Value[0] > pivotValue[0] && ema3Value[0] > pivotValue[0];
bool buyCondition3 = ema1Value[0] - ema2Value[0] > DiffEMA1EMA2*_Point && ema2Value[0] - ema3Value[0] > DiffEMA2EMA3*_Point;
//sell conditions
bool sellCondition2 = ema1Value[0] < pivotValue[0] && ema2Value[0] < pivotValue[0] && ema3Value[0] < pivotValue[0];
bool sellCondition3 = ema2Value[0] - ema1Value[0] > DiffEMA1EMA2*_Point && ema3Value[0] - ema2Value[0] > DiffEMA2EMA3*_Point;
bool buyCondition1;
bool buyCondition4;
bool buyCondition5;
bool buyCondition6;
bool sellCondition1;
bool sellCondition4;
bool sellCondition5;
bool sellCondition6;
if(CheckPrevPivot){
buyCondition1 = prevPivot < pivotValue[0];
sellCondition1 = prevPivot > pivotValue[0];
}
else{
buyCondition1 = true;
sellCondition1 = true;
}
if(CheckOnlyLowHigh){
buyCondition4 = bar[0].low < ema3Value[0]+Ema3Offset*_Point;
sellCondition4 = bar[0].high > ema3Value[0]-Ema3Offset*_Point;
}
else{
buyCondition4 = prevBid > ema3Value[0]+Ema3Offset*_Point && bid < ema3Value[0]+Ema3Offset*_Point;
sellCondition4 = prevBid < ema3Value[0]-Ema3Offset*_Point && bid > ema3Value[0]-Ema3Offset*_Point;
}
if(CheckEMAsDirection){
buyCondition5 = ema1Value[1] < ema1Value[0] && ema2Value[1] < ema2Value[0] && ema3Value[1] < ema3Value[0];
sellCondition5 = ema1Value[1] > ema1Value[0] && ema2Value[1] > ema2Value[0] && ema3Value[1] > ema3Value[0];
}
else{
buyCondition5 = true;
sellCondition5 = true;
}
if(SR2Check){
buyCondition6 = bid < R2[0];
sellCondition6 = bid > S2[0];
}
else{
buyCondition6 = true;
sellCondition6 = true;
}
//--- market execution
if(spreadOK && onlyOneTrade && notMonday && notSameBar && buyCondition1 && buyCondition2 && buyCondition3 && buyCondition4 && buyCondition5 && buyCondition6){
//set stop loss
switch(SLsetup){
case SL_FixPoint:
fsl = bid - SLpoints * _Point;
break;
case SL_SR1:
fsl = S1[0];
break;
case SL_SR2:
fsl = S2[0];
break;
case SL_SR3:
fsl = S3[0];
break;
default:
break;
}
//set take profit
ftp = SetBuyProfitLimit(TPsetup);
//reset stop loss if TP need to be calculated first
if(SLsetup == SL_TPratio){
fsl = bid - (ftp - ask)/TpSlRatio;
}
//set volume of transaction
if(Lots != 0){
fvolume = Lots;
}
else{
fvolume = LotsCalculator(bid,fsl,accountBalance);
}
trade.Buy(fvolume,_Symbol,ask,fsl,ftp);
lastOpen = bar[0].open;
}
if(spreadOK && onlyOneTrade && notMonday && notSameBar && sellCondition1 && sellCondition2 && sellCondition3 && sellCondition4 && sellCondition5 && sellCondition6){
//set stop loss
switch(SLsetup){
case SL_FixPoint:
fsl = ask + SLpoints * _Point;
break;
case SL_SR1:
fsl = R1[0];
break;
case SL_SR2:
fsl = R2[0];
break;
case SL_SR3:
fsl = R3[0];
break;
default:
break;
}
//set take profit
ftp = SetSellProfitLimit(TPsetup);
//reset stop loss if TP need to be calculated first
if(SLsetup == SL_TPratio){
fsl = ask + (bid - ftp)/TpSlRatio;
}
//set volume of transaction
if(Lots != 0){
fvolume = Lots;
}
else{
fvolume = LotsCalculator(ask,fsl,accountBalance);
}
trade.Sell(fvolume,_Symbol,bid,fsl,ftp);
lastOpen = bar[0].open;
}
prevBid = bid;
//--- conditional exit
if(positionTotal > 0){
switch(ExitSetup){
case InstantEMA1EMA2cross:
if(ema1Value[0] < ema2Value[0]){
CloseAllLongPositions();
}
else{
CloseAllShortPositions();
}
break;
case InstantEMA1EMA3cross:
if(ema1Value[0] < ema3Value[0]){
CloseAllLongPositions();
}
else{
CloseAllShortPositions();
}
break;
case DelayEMA1EMA2cross:
if(ema1Value[1] < ema2Value[1]){
CloseAllLongPositions();
}
else{
CloseAllShortPositions();
}
break;
case DelayEMA1EMA3cross:
if(ema1Value[1] < ema3Value[1]){
CloseAllLongPositions();
}
else{
CloseAllShortPositions();
}
break;
default:
break;
}
}
//--- safe mode and trailing mode
if((SafeMode || TrailingMode)){
//reset arrays if no position
if(positionTotal == 0 && arraySize > 0){
arraySize = 0;
prevPositionTotal = 0;
ArrayResize(positionTicket,arraySize,10);
ArrayResize(safeActivationPrice,arraySize,10);
ArrayResize(safeSL,arraySize,10);
ArrayResize(trailingActivationPrice,arraySize,10);
ArrayResize(trailingDistance,arraySize,10);
}
//if at least one position is open then follow up and place new SL if conditions are fulfilled
if(positionTotal > 0){
for(int i=0; i<arraySize; i++){
if(PositionSelectByTicket(positionTicket[i])){
//get information of the position
positionType = PositionGetInteger(POSITION_TYPE);
positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
positionCurrentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
positionTP = PositionGetDouble(POSITION_TP);
positionSL = PositionGetDouble(POSITION_SL);
if(SafeMode){
if(positionType == POSITION_TYPE_BUY && positionCurrentPrice > safeActivationPrice[i] && positionSL < positionOpenPrice){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeSL[i],positionTP);
positionSL = PositionGetDouble(POSITION_SL);
ObjectDelete(0,"Safe Activation #"+IntegerToString(positionTicket[i]));
if(orderStatus[1] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){
trade.OrderDelete(currentOrderTickets[1]);
orderStatus[1] = false;
}
}
else if(positionType==POSITION_TYPE_SELL && positionCurrentPrice < safeActivationPrice[i] && positionSL > positionOpenPrice){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeSL[i],positionTP);
positionSL = PositionGetDouble(POSITION_SL);
ObjectDelete(0,"Safe Activation #"+IntegerToString(positionTicket[i]));
if(orderStatus[0] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){
trade.OrderDelete(currentOrderTickets[0]);
orderStatus[0] = false;
}
}
}
if(TrailingMode){
if(positionType == POSITION_TYPE_BUY){
trailingSL = NormalisePrice(positionCurrentPrice - trailingDistance[i]);
if(trailingSL<0)trailingSL = 0;
if(positionCurrentPrice > trailingActivationPrice[i] && positionSL<trailingSL){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),trailingSL,positionTP);
positionSL = PositionGetDouble(POSITION_SL);
ObjectDelete(0,"Trailing Activation #"+IntegerToString(positionTicket[i]));
//remove second order
if(orderStatus[1] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){
trade.OrderDelete(currentOrderTickets[1]);
orderStatus[1] = false;
}
}
}
else if(positionType==POSITION_TYPE_SELL){
trailingSL = NormalisePrice(positionCurrentPrice + trailingDistance[i]);
if(trailingSL<0)trailingSL = 0;
if(positionCurrentPrice < trailingActivationPrice[i] && positionSL>trailingSL){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),trailingSL,positionTP);
positionSL = PositionGetDouble(POSITION_SL);
ObjectDelete(0,"Trailing Activation #"+IntegerToString(positionTicket[i]));
if(orderStatus[0] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){
trade.OrderDelete(currentOrderTickets[0]);
orderStatus[0] =false;
}
}
}
}
}
}
}
}
}
//+------------------------------------------------------------------+