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

209 lines
8.9 KiB
MQL5

//+------------------------------------------------------------------+
//| JPBP.mqh |
//| Copyright 2018, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#include <Trade\Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
//| global variables |
//+------------------------------------------------------------------+
//--- main input parameters
input ulong MagicNumber = 1234;
input ENUM_TIMEFRAMES TimeFrame = PERIOD_D1;
input int AddPoint = 50;
input double TpSlRatio = 2; //take profit/stop loss ratio
input double SlPercent = 2;
input bool SafeMode = false;//safe mode on
input double SafeActivationRatio = 4;
input double SafeSlRatio = 2;
input bool TrailingMode =false;//trailing mode on
input double TrailingActivationRatio = 6;
input double TrailingDistance = 20; //trailing distance
input bool CancelOrderOnTP = true; //cancel orders on TP
input bool CancelOrderOnSL = true; //cancel orders on profitable SL
input bool CancelOrderOnLoss = false; //cancel orders on non-profitable SL
input bool OrderOnce = false; //place orders only once
input bool DrawLines = true; //Draw safe and trailing activation lines
input int TimeOffset = 0;
//--- market variables
double volumeStep;
double tickSize;
double tickPrice;
double bid;
double ask;
long tickVolume[];
MqlRates bar[];
double lastOpen;
//--- time variables
MqlDateTime firstBar;
MqlDateTime today;
MqlDateTime startTime[];
MqlDateTime endTime[];
datetime lastRefreshDay;
datetime prevDay;
//--- account variables
double accountBalance;
double accountEquity;
//--- trade variables
//--- orders and positions handling system variables
bool orderConditions;
bool resetOrderPlaced;
bool orderPlaced[2];
int arrayIndex;
int arraySize;
double cancellingSL[2];
int prevPositionTotal;
int positionTotal;
ulong positionTicket[];
double safeActivationPrice[];
double safeSL[];
double trailingActivationPrice[];
double trailingDistance[];
double trailingSL;
long positionType;
double positionOpenPrice;
double positionCurrentPrice;
double positionTP;
double positionSL;
ulong lastPositionTicket;
ulong posTicket;
ulong histOrderTicket;
ulong histDealTicket;
double histOrderPrice;
double initialPositionSL;
bool profitableSL;
bool timeSet;
//+------------------------------------------------------------------+
//| functions |
//+------------------------------------------------------------------+
double NormalisePrice(double p){
return (MathRound(p/tickSize)*tickSize);
}
double LotsCalculator(double openPrice, double closePrice, double balance){
double lots = NormalizeDouble(((balance*(SlPercent/100))/(MathAbs(openPrice-closePrice)*(tickPrice/tickSize)))/volumeStep,0)*volumeStep;
if(lots < SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)){
lots = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
}
else if(lots > SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX)){
lots = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
}
return lots;
}
void setVariables(){
lastOpen = 0;
volumeStep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
tickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
tickPrice = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
}
void refreshVariables(){
bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
accountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
ArraySetAsSeries(bar,true);
CopyRates(_Symbol,TimeFrame,0,2,bar);
TimeToStruct(bar[1].time,firstBar);
TimeToStruct(TimeCurrent(),today);
//refresh once a day
if(today.day != lastRefreshDay){
volumeStep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
tickSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
tickPrice = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
lastRefreshDay = today.day;
}
}
void AddPosition(){ //add a position into the safe and trailing system. The position has to be previously selected and checked
arrayIndex = arraySize;
arraySize = arraySize + 1;
ArrayResize(positionTicket,arraySize,10);
positionTicket[arrayIndex] = PositionGetInteger(POSITION_TICKET);
positionType = PositionGetInteger(POSITION_TYPE);
positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
positionSL = PositionGetDouble(POSITION_SL);
//check if the SL is already in a safe/profitable place
if((positionType == POSITION_TYPE_BUY && positionSL < positionOpenPrice) || (positionType==POSITION_TYPE_SELL && positionSL > positionOpenPrice)){
initialPositionSL = positionSL; //if not profitable SL then the current SL is the initial SL of the position
profitableSL = false;
}
else{
profitableSL = true;
if(TrailingMode){
HistorySelect(0,TimeCurrent());
for(int j=HistoryOrdersTotal()-1; j>=0; j--){
histOrderTicket = HistoryOrderGetTicket(j);
if(HistoryOrderGetInteger(histOrderTicket,ORDER_POSITION_ID) == PositionGetInteger(POSITION_IDENTIFIER)){
initialPositionSL = HistoryOrderGetDouble(histOrderTicket,ORDER_SL);
}
}
}
}
if(SafeMode && !profitableSL){
ArrayResize(safeActivationPrice,arraySize,10);
ArrayResize(safeSL,arraySize,10);
if(positionType == POSITION_TYPE_BUY){
safeActivationPrice[arrayIndex] = positionOpenPrice + (positionOpenPrice-positionSL)*SafeActivationRatio;
safeSL[arrayIndex] = NormalisePrice(positionOpenPrice + (positionOpenPrice-positionSL)*SafeSlRatio);
if(safeSL[arrayIndex]<0)safeSL[arrayIndex] = 0;
}
else if(positionType==POSITION_TYPE_SELL){
safeActivationPrice[arrayIndex] = positionOpenPrice - (positionSL-positionOpenPrice)*SafeActivationRatio;
safeSL[arrayIndex] = NormalisePrice(positionOpenPrice - (positionSL-positionOpenPrice)*SafeSlRatio);
if(safeSL[arrayIndex]<0)safeSL[arrayIndex] = 0;
}
if(DrawLines){
ObjectCreate(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJ_HLINE,0,0,safeActivationPrice[arrayIndex]);
ObjectSetInteger(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_COLOR,clrDodgerBlue);
ObjectSetInteger(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_STYLE,STYLE_DASH);
}
}
if(TrailingMode){
ArrayResize(trailingActivationPrice,arraySize,10);
ArrayResize(trailingDistance,arraySize,10);
if(positionType == POSITION_TYPE_BUY){
trailingActivationPrice[arrayIndex] = positionOpenPrice + (positionOpenPrice-initialPositionSL)*TrailingActivationRatio;
trailingDistance[arrayIndex] = (trailingActivationPrice[arrayIndex]-positionOpenPrice)*(TrailingDistance/100);
}
else if(positionType==POSITION_TYPE_SELL){
trailingActivationPrice[arrayIndex] = positionOpenPrice - (initialPositionSL-positionOpenPrice)*TrailingActivationRatio;
trailingDistance[arrayIndex] = (positionOpenPrice - trailingActivationPrice[arrayIndex])*(TrailingDistance/100);
}
if(DrawLines){
ObjectCreate(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJ_HLINE,0,0,trailingActivationPrice[arrayIndex]);
ObjectSetInteger(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_COLOR,clrMediumOrchid);
ObjectSetInteger(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),OBJPROP_STYLE,STYLE_DASH);
}
}
}
void CloseAllLongPositions(){
for(int i=0; i< PositionsTotal(); i++){
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) trade.PositionClose(PositionGetTicket(i));
}
}
void CloseAllShortPositions(){
for(int i=0; i< PositionsTotal(); i++){
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) trade.PositionClose(PositionGetTicket(i));
}
}
void CloseAllPositions(){
for(int i=0; i< PositionsTotal(); i++){
if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol) trade.PositionClose(PositionGetTicket(i));
}
}