270 lines
11 KiB
MQL5
270 lines
11 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| twoWavesLimits.mq5 |
|
|
//| Copyright 2018, Benjamin Pillet |
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#include "JPBP.mqh"
|
|
|
|
enum limitPolicy
|
|
{
|
|
passthrough,//pass through
|
|
closeBeyond,//close beyond
|
|
};
|
|
enum limitUsed
|
|
{
|
|
wave1,//use wave 1 limit
|
|
wave2,//use wave 2 limit
|
|
};
|
|
|
|
//--- 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 limitPolicy EntryPolicy = closeBeyond; //entry policy
|
|
|
|
//--- exit input parameters
|
|
input int SLpoints = 300;
|
|
|
|
//--- global variables
|
|
datetime expDate;
|
|
ulong currentOrderTickets[2];
|
|
bool orderStatus[2];
|
|
datetime baseStartTime;
|
|
|
|
double fprice;
|
|
double fsl;
|
|
double ftp;
|
|
double fvolume;
|
|
double prevBid;
|
|
|
|
double w1High;
|
|
double w1Low;
|
|
double w2High;
|
|
double w2Low;
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//---
|
|
//--- 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)
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//--- 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;
|
|
|
|
//--- Calculate wave limits
|
|
|
|
|
|
//--- Define conditions for instant execution
|
|
//general conditions
|
|
bool onlyOneTrade;
|
|
if(OnePos) onlyOneTrade = positionTotal == 0; else onlyOneTrade = true;
|
|
|
|
//buy conditions
|
|
|
|
|
|
//sell conditions
|
|
|
|
|
|
//--- market execution
|
|
//buy
|
|
if(){
|
|
//set stoploss
|
|
|
|
//set take profit
|
|
|
|
//set volume of transaction
|
|
|
|
}
|
|
|
|
|
|
//--- 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|