448 lines
18 KiB
MQL5
448 lines
18 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| SRL.mq5 |
|
||
|
//| Benjamin Pillet |
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
#include "base.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_SR,//base on upper-lower limits
|
||
|
};
|
||
|
enum TPstrat
|
||
|
{
|
||
|
TP_SLratio,//ratio of stop loss
|
||
|
TP_SR,
|
||
|
TP_Moving
|
||
|
};
|
||
|
enum limitPolicy
|
||
|
{
|
||
|
passthrough,//pass through
|
||
|
closeBeyond,//close beyond
|
||
|
wave2InsidePass,
|
||
|
wave2InsideBeyond,
|
||
|
};
|
||
|
enum limitToUse
|
||
|
{
|
||
|
SR1,//use wave one limits
|
||
|
SR2,//use wave two limits
|
||
|
highestLowest //use the highest or lowest limits
|
||
|
};
|
||
|
|
||
|
//--- 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
|
||
|
input limitToUse LimitToUse = SR1;//limit to use
|
||
|
input bool OnePerLimit = true; //open only one time on the same limit
|
||
|
|
||
|
//--- exit input 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\\SRL\\SandR.ex5";
|
||
|
|
||
|
double fprice;
|
||
|
double fsl;
|
||
|
double ftp;
|
||
|
double fvolume;
|
||
|
|
||
|
|
||
|
int SandRHandle;
|
||
|
double R1[];
|
||
|
double R2[];
|
||
|
double S1[];
|
||
|
double S2[];
|
||
|
|
||
|
double upperLimit;
|
||
|
double lastupperLimit;
|
||
|
double lowerLimit;
|
||
|
double lastlowerLimit;
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Expert initialization function |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int OnInit()
|
||
|
{
|
||
|
//---
|
||
|
//--- set variables
|
||
|
setVariables();
|
||
|
trade.SetExpertMagicNumber(MagicNumber);
|
||
|
arraySize = 0;
|
||
|
orderPlaced[0] = false;
|
||
|
orderPlaced[1] = false;
|
||
|
positionTotal = 0;
|
||
|
SandRHandle = iCustom(_Symbol,TimeFrame,indPath,2,50);
|
||
|
|
||
|
//---Set array as series
|
||
|
ArraySetAsSeries(R1,true);
|
||
|
ArraySetAsSeries(R2,true);
|
||
|
ArraySetAsSeries(S1,true);
|
||
|
ArraySetAsSeries(S2,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(SandRHandle);
|
||
|
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Expert tick function |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void OnTick()
|
||
|
{
|
||
|
//--- get market info
|
||
|
refreshVariables();
|
||
|
|
||
|
//---Acquires indicators informations
|
||
|
CopyBuffer(SandRHandle,0,0,3,R1);
|
||
|
CopyBuffer(SandRHandle,1,0,3,R2);
|
||
|
CopyBuffer(SandRHandle,5,0,3,S1);
|
||
|
CopyBuffer(SandRHandle,6,0,3,S2);
|
||
|
|
||
|
//--- 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_Moving)){
|
||
|
AddPosition();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--- 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)));
|
||
|
ObjectDelete(0,"Safe Wave Activation #"+IntegerToString(HistoryDealGetInteger(histDealTicket,DEAL_POSITION_ID)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
prevPositionTotal = positionTotal;
|
||
|
|
||
|
|
||
|
//--- Define conditions for instant execution
|
||
|
//set limits
|
||
|
|
||
|
switch(LimitToUse){
|
||
|
case SR1:
|
||
|
upperLimit = R1[0] + AddPoint;
|
||
|
lowerLimit = S1[0] - AddPoint;
|
||
|
break;
|
||
|
case SR2:
|
||
|
upperLimit = R2[0] + AddPoint;
|
||
|
lowerLimit = S2[0] - AddPoint;
|
||
|
break;
|
||
|
case highestLowest:
|
||
|
if(R2[0] > R1[0]) upperLimit = R2[0] + AddPoint; else upperLimit = R1[0] + AddPoint;
|
||
|
if(S2[0] < S1[0]) lowerLimit = S2[0] - AddPoint; else lowerLimit = S1[0] - AddPoint;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//general conditions
|
||
|
bool notSameBar = lastOpen != bar[0].open;
|
||
|
bool onlyOneTrade;
|
||
|
bool upperLimitChanged;
|
||
|
bool lowerLimitChanged;
|
||
|
|
||
|
if(OnePos) onlyOneTrade = positionTotal == 0; else onlyOneTrade = true;
|
||
|
if(OnePerLimit){
|
||
|
upperLimitChanged = upperLimit != lastupperLimit;
|
||
|
lowerLimitChanged = lowerLimit != lastlowerLimit;
|
||
|
}
|
||
|
else{
|
||
|
upperLimitChanged = true;
|
||
|
lowerLimitChanged = true;
|
||
|
}
|
||
|
|
||
|
bool bc = false;
|
||
|
bool sc = false;
|
||
|
if(EntryPolicy == passthrough){
|
||
|
if((prevBid < upperLimit && bid > upperLimit) || (prevBid > lowerLimit && bid < lowerLimit)) bc = true;
|
||
|
if((prevBid < upperLimit && bid > upperLimit) || (prevBid > lowerLimit && bid < lowerLimit)) sc = true;
|
||
|
}
|
||
|
if(EntryPolicy == closeBeyond){
|
||
|
if(bar[1].close > upperLimit && bar[1].open < upperLimit) bc = true;
|
||
|
if(bar[1].close < lowerLimit && bar[1].open > lowerLimit) sc = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--- market execution
|
||
|
bool upper = false;
|
||
|
if(MathAbs(R1[0]-bid) < MathAbs(S1[0]-bid)) upper = true;
|
||
|
//buy
|
||
|
if(bc && onlyOneTrade && ((upperLimitChanged && upper) || (lowerLimitChanged && !upper))){
|
||
|
//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_SR:
|
||
|
fsl = bid - (upperLimit - lowerLimit)/SLbaseRatio;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//set take profit
|
||
|
switch(TPsetup){
|
||
|
case TP_SLratio:
|
||
|
ftp = ask + (bid-fsl)*TpSlRatio;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//set volume of transaction
|
||
|
if(Lots != 0){
|
||
|
fvolume = Lots;
|
||
|
}
|
||
|
else{
|
||
|
fvolume = LotsCalculator(bid,fsl,accountBalance);
|
||
|
}
|
||
|
|
||
|
trade.Buy(fvolume,_Symbol,ask,fsl,ftp);
|
||
|
lastupperLimit = upperLimit;
|
||
|
}
|
||
|
|
||
|
//sell
|
||
|
if(sc && onlyOneTrade && ((upperLimitChanged && upper) || (lowerLimitChanged && !upper))){
|
||
|
//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_SR:
|
||
|
fsl = ask + (upperLimit-lowerLimit)/SLbaseRatio;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//set take profit
|
||
|
switch(TPsetup){
|
||
|
case TP_SLratio:
|
||
|
ftp = bid - (fsl - ask)*TpSlRatio;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//set volume of transaction
|
||
|
if(Lots != 0){
|
||
|
fvolume = Lots;
|
||
|
}
|
||
|
else{
|
||
|
fvolume = LotsCalculator(ask,fsl,accountBalance);
|
||
|
}
|
||
|
trade.Sell(fvolume,_Symbol,bid,fsl,ftp);
|
||
|
lastlowerLimit = lowerLimit;
|
||
|
}
|
||
|
//--- reset prev variables
|
||
|
prevAsk = ask;
|
||
|
prevBid = bid;
|
||
|
|
||
|
//--- safe mode and trailing mode
|
||
|
if((SafeMode || TrailingMode || TPsetup == TP_Moving)){
|
||
|
//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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}*/
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|