twoWavesLimits/JPBP.mqh
super.admin 62a907ea44 convert
2025-05-30 16:34:23 +02:00

318 lines
12 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 group "main parameters"
input ulong MagicNumber = 1234;
input ENUM_TIMEFRAMES TimeFrame = PERIOD_D1;
input double Lots = 0; //Lots, 0=compound
input double TpSlRatio = 2; //take profit/stop loss ratio
input double SlPercent = 2;
input int AddPoint = 50;
input int TimeOffset = 0;
input group "Trailing and safe modes"
input bool SafeWave = false;//safe wave on
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 DrawLines = true; //Draw safe and trailing activation lines
input group "orders"
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
//--- market variables
double volumeStep;
double tickSize;
double tickPrice;
double bid;
double ask;
bool barChanged;
long tickVolume[];
MqlRates bar[];
//--- previous tick variables
double prevBid;
double prevAsk;
double prevOpen; //open price of bar of the last tick
//--- time variables
MqlDateTime firstBar;
MqlDateTime today;
MqlDateTime startTime[];
MqlDateTime endTime[];
datetime lastRefreshDay;
datetime prevDay;
//--- account variables
double accountBalance;
double accountEquity;
//--- trade variables
double lastOpen; //open price of the bar during which the last position was opened
//--- 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;
double safeWaveActivationPrice[];
double safeWaveSL[];
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 |
//+------------------------------------------------------------------+
enum limitMode{
IS_HIGHER,
IS_LOWER,
CLOSE_ABOVE,
CLOSE_BELOW,
OPEN_ABOVE,
OPEN_BELOW,
CLOSEandOPEN_ABOVE,
CLOSEandOPEN_BELOW,
PASS_ABOVE,
PASS_BELOW
};
enum priceMode{
BID, //BID
ASK //ASK
};
bool Limit(double limitValue, limitMode mode, priceMode pm = BID){
double val=0;
double prevVal=0;
if(pm == BID){
val = bid;
prevVal = prevBid;
}
else{
val = ask;
prevVal = prevAsk;
}
switch(mode){
case IS_HIGHER:
if(val > limitValue) return true;
else return false;
break;
case IS_LOWER:
if(val < limitValue) return true;
else return false;
break;
case CLOSE_ABOVE:
if(bar[1].close > limitValue && bar[1].open < limitValue) return true;
else return false;
break;
case CLOSE_BELOW:
if(bar[1].close < limitValue && bar[1].open > limitValue) return true;
else return false;
break;
case OPEN_ABOVE:
if(bar[0].open > limitValue && bar[1].open < limitValue) return true;
else return false;
break;
case OPEN_BELOW:
if(bar[0].open < limitValue && bar[1].open > limitValue) return true;
else return false;
break;
case CLOSEandOPEN_ABOVE:
if(bar[1].close > limitValue && bar[1].open < limitValue && bar[0].open > limitValue) return true;
else return false;
break;
case CLOSEandOPEN_BELOW:
if(bar[1].close < limitValue && bar[1].open > limitValue && bar[0].open < limitValue) return true;
else return false;
break;
case PASS_ABOVE:
if(prevVal < limitValue && val > limitValue) return true;
else return false;
break;
case PASS_BELOW:
if(prevVal > limitValue && val < limitValue) return true;
else return false;
break;
default:
return false;
break;
}
}
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,3,bar);
TimeToStruct(bar[1].time,firstBar);
TimeToStruct(TimeCurrent(),today);
//check if new bar start
if(bar[0].open != prevOpen) barChanged = true;
else barChanged = false;
//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 getReadyForNextTick(){
prevBid = bid;
prevAsk = ask;
prevOpen = bar[0].open;
prevPositionTotal = positionTotal;
}
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);
}
}
if(SafeWave){
ArrayResize(safeWaveActivationPrice,arraySize,10);
ArrayResize(safeWaveSL,arraySize,10);
}
}
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));
}
}