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

481 lines
19 KiB
MQL5

//+------------------------------------------------------------------+
//| twoWavesLimits.mq5 |
//| Copyright 2018, Benjamin Pillet |
//| |
//+------------------------------------------------------------------+
#include "JPBP.mqh";
#include <dataDL.mqh>;
enum SLstrat
{
SL_FixPoint,//fix amount of points
SL_LastBarRatio,//based on last bar high-low distance
SL_TPratio,//ratio of take profit
SL_Wave1,//use wave 1
SL_Wave2//use wave 2
};
enum TPstrat
{
TP_SLratio,//ratio of stop loss
TP_MovingW1
};
enum limitPolicy
{
passthrough,//pass through
closeBeyond,//close beyond
wave2InsidePass,
wave2InsideBeyond,
};
enum limitToUse
{
wave1,//use wave one limits
wave2,//use wave two limits
highestLowest //use the highest or lowest limits
};
//--- Entry input parameters
input group "entry parameters"
input int MaxSpread = 0; //check spread and set a maximum, 0 = no check
input bool OnePos = false; //open only one position
input limitPolicy EntryPolicy = closeBeyond; //entry policy
input limitToUse LimitToUse = wave2;//limit to use
input bool OnePerLimit = true; //open only one time on the same limit
input double MinSpreadRatio = 1; //minimal loss as ratio of the spead
//--- exit input parameters
input group "exit parameters"
input SLstrat SLsetup = SL_FixPoint;//stop loss policy
input int SLpoints = 300;
input double SLbaseRatio = 2;
input TPstrat TPsetup = TP_SLratio;//take profit policy
//--- global variables
datetime expDate;
ulong currentOrderTickets[2];
bool orderStatus[2];
datetime baseStartTime;
string indPath = "Shared Projects\\twoWavesLimits\\twoWaves.ex5";
double fprice;
double fsl;
double ftp;
double fvolume;
int twoWavesHandle;
double w1High[];
double w1Low[];
double w2High[];
double w2Low[];
double buyLimit;
double lastBuyLimit;
double sellLimit;
double lastSellLimit;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//--- set variables
//if(gatherData || askML)initialiseIndicators();
setVariables();
trade.SetExpertMagicNumber(MagicNumber);
arraySize = 0;
orderPlaced[0] = false;
orderPlaced[1] = false;
positionTotal = 0;
twoWavesHandle = iCustom(_Symbol,TimeFrame,indPath,TimeFrame);
//---Set array as series
ArraySetAsSeries(w1High,true);
ArraySetAsSeries(w1Low,true);
ArraySetAsSeries(w2High,true);
ArraySetAsSeries(w2Low,true);
//--- 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)
{
//---
IndicatorRelease(twoWavesHandle);
FileClose(fhBuy);
//FileClose(fileHandle);
//assignClassAll();
//saveDataArff(ORDER_TYPE_BUY,false);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- get market info
refreshVariables();
if(gatherData) setMinMax();
if(gatherData) endSequences();
//updateSequences();
//---Acquires indicators informations
CopyBuffer(twoWavesHandle,0,0,3,w1High);
CopyBuffer(twoWavesHandle,1,0,3,w1Low);
CopyBuffer(twoWavesHandle,2,0,3,w2High);
CopyBuffer(twoWavesHandle,3,0,3,w2Low);
//--- 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 || TPsetup == TP_MovingW1 || SafeWave)){
AddPosition();
//getData(posTicket,PositionGetInteger(POSITION_TYPE));
}
}
}
}
//--- remove lines if a position was closed
if(positionTotal < prevPositionTotal){
//assignClass();
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)));
ObjectDelete(0,"Safe Wave Activation #"+IntegerToString(HistoryDealGetInteger(histDealTicket,DEAL_POSITION_ID)));
}
}
prevPositionTotal = positionTotal;
//--- Define conditions for instant execution
//set limits
switch(LimitToUse){
case wave1:
buyLimit = w1High[0] + AddPoint;
sellLimit = w1Low[0] - AddPoint;
break;
case wave2:
buyLimit = w2High[0] + AddPoint;
sellLimit = w2Low[0] - AddPoint;
break;
case highestLowest:
if(w2High[0] > w1High[0]) buyLimit = w2High[0] + AddPoint; else buyLimit = w1High[0] + AddPoint;
if(w2Low[0] < w1Low[0]) sellLimit = w2Low[0] - AddPoint; else sellLimit = w1Low[0] - AddPoint;
break;
}
//general conditions
bool notSameBar = lastOpen != bar[0].open;
bool onlyOneTrade;
bool buyLimitChanged;
bool sellLimitChanged;
if(OnePos) onlyOneTrade = positionTotal == 0; else onlyOneTrade = true;
if(OnePerLimit){
buyLimitChanged = buyLimit != lastBuyLimit;
sellLimitChanged = sellLimit != lastSellLimit;
}
else{
buyLimitChanged = true;
sellLimitChanged = true;
}
bool bc = false;
bool sc = false;
if(EntryPolicy == passthrough){
if(Limit(buyLimit,PASS_ABOVE,BID) && buyLimit != 0) bc = true;
if(Limit(sellLimit,PASS_BELOW,ASK) && sellLimit != 0) sc = true;
}
if(EntryPolicy == closeBeyond){
if(Limit(buyLimit,CLOSEandOPEN_ABOVE)) bc = true;
if(Limit(sellLimit,CLOSEandOPEN_BELOW)) sc = true;
}
//--- market execution
//buy
if(bc && onlyOneTrade && buyLimitChanged){
//set stoploss
switch(SLsetup){
case SL_FixPoint:
fsl = bid - SLpoints * _Point;
break;
case SL_LastBarRatio:
fsl = bid - (bar[1].high-bar[1].low)/SLbaseRatio;
break;
case SL_Wave1:
fsl = w1Low[0];
break;
case SL_Wave2:
fsl = w2Low[0];
break;
default:
break;
}
//set take profit
ftp = ask + (bid-fsl)*TpSlRatio;
//set volume of transaction
if(bid > fsl && bid-fsl > (ask-bid)*MinSpreadRatio){
if(Lots != 0){
fvolume = Lots;
}
else{
fvolume = LotsCalculator(bid,fsl,accountBalance);
}
if(askML || gatherData) getData(-1,ORDER_TYPE_BUY);
//if(askML) saveDataArffLive();
datetime ptime = TimeCurrent();
if(true){
//if(false){
//if(askWekaFile(ORDER_TYPE_BUY)){ //always true if askML is false
if(trade.Buy(fvolume,_Symbol,ask,fsl,ftp)){
if(gatherData) setID(ptime);
lastBuyLimit = buyLimit;
lastOpen = bar[0].open;
}
}
}
}
//sell
if(sc && onlyOneTrade && sellLimitChanged){
//set stoploss
switch(SLsetup){
case SL_FixPoint:
fsl = ask + SLpoints * _Point;
break;
case SL_LastBarRatio:
fsl = ask + (bar[1].high-bar[1].low)/SLbaseRatio;
break;
case SL_Wave1:
fsl = w1High[0];
break;
case SL_Wave2:
fsl = w2High[0];
break;
default:
break;
}
//set take profit
ftp = bid - (fsl - ask)*TpSlRatio;
//set volume of transaction
if(ask < fsl && fsl-ask > (ask-bid)*MinSpreadRatio){
if(Lots != 0){
fvolume = Lots;
}
else{
fvolume = LotsCalculator(ask,fsl,accountBalance);
}
//if(askML || gatherData) getData(-1,ORDER_TYPE_SELL);
//if(askML) saveDataArffLive();
datetime ptime = TimeCurrent();
if(false){
//if(askWekaFile(ORDER_TYPE_SELL)){ //always true if askML is false
if(trade.Sell(fvolume,_Symbol,bid,fsl,ftp)){
if(gatherData) setID(ptime);
lastSellLimit = sellLimit;
lastOpen = bar[0].open;
}
}
}
}
//--- safe mode and trailing mode
if((SafeMode || TrailingMode || TPsetup == TP_MovingW1 || SafeWave)){
//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;
}
}
}
}
if(TPsetup == TP_MovingW1){
if(positionType == POSITION_TYPE_BUY && bar[0].open < w1High[0] && positionTP != w1High[0] && w1High[0] != w2High[0]){
//PrintFormat("Hello");
trade.PositionModify(PositionGetInteger(POSITION_TICKET),positionSL,w1High[0]);
}
if(positionType == POSITION_TYPE_SELL && bar[0].open > w1Low[0] && positionTP != w1Low[0] && w1Low[0] != w2Low[0]){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),positionSL,w1Low[0]);
}
}
if(SafeWave){
if(positionType == POSITION_TYPE_BUY){
if(bar[2].close > bar[2].open && bar[1].close < bar[1].open){
safeWaveActivationPrice[i] = bar[2].high;
if(bar[1].high > safeWaveActivationPrice[i]){
safeWaveActivationPrice[i] = bar[1].high;
}
safeWaveSL[i] = bar[1].low;
ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]);
ObjectCreate(0,"Safe Wave Activation #"+positionTicket[i],OBJ_HLINE,0,0,safeWaveActivationPrice[arrayIndex]);
ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_COLOR,clrOrange);
ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_STYLE,STYLE_DASH);
}
if(bar[1].low < safeWaveSL[i]){
safeWaveSL[i] = bar[1].low;
}
if(positionCurrentPrice > safeWaveActivationPrice[i] && positionSL < safeWaveSL[i]){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeWaveSL[i],positionTP);
positionSL = PositionGetDouble(POSITION_SL);
ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]);
if(orderStatus[1] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL && positionSL > positionOpenPrice){
trade.OrderDelete(currentOrderTickets[1]);
orderStatus[1] = false;
}
}
}
if(positionType == POSITION_TYPE_SELL){
if(bar[2].close < bar[2].open && bar[1].close > bar[1].open){
safeWaveActivationPrice[i] = bar[2].low;
if(bar[1].low < safeWaveActivationPrice[i]){
safeWaveActivationPrice[i] = bar[1].low;
}
safeWaveSL[i] = bar[1].high;
ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]);
ObjectCreate(0,"Safe Wave Activation #"+positionTicket[i],OBJ_HLINE,0,0,safeWaveActivationPrice[arrayIndex]);
ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_COLOR,clrOrange);
ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_STYLE,STYLE_DASH);
}
if(bar[1].high > safeWaveSL[i]){
safeWaveSL[i] = bar[1].high;
}
if(positionCurrentPrice < safeWaveActivationPrice[i] && positionSL > safeWaveSL[i]){
trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeWaveSL[i],positionTP);
positionSL = PositionGetDouble(POSITION_SL);
ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]);
if(orderStatus[0] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL && positionSL < positionOpenPrice){
trade.OrderDelete(currentOrderTickets[0]);
orderStatus[0] = false;
}
}
}
}
}
}
}
}
getReadyForNextTick();
}
void OnTrade()
{
//assignClass();
//PrintFormat("instance index: "+instanceIndex);
}
//+------------------------------------------------------------------+