//+------------------------------------------------------------------+
//| Trading Manager.mq4 |
//| Copyright MQL BLUE |
//| http://www.mqlblue.com |
//+------------------------------------------------------------------+
#property copyright "Copyright MQL BLUE"
#property link "https://www.mqlblue.com"
#property version "2.00"
#property strict
//---- definitions
#define Version "2.00"
#include <stderror.mqh>
#include <stdlib.mqh>
// **** EA PARAMS *****************
input string SLTPParams = "--- SL & TP -------------------";
input int StopLoss = 20;
input int TakeProfit = 40;
input string BEParams = "--- BreakEven -----------------";
input bool UseBreakEven = true;
input int BEActivation = 50;
input int BELevel = 10;
input string TS1Params = "--- Trailing Stop -------------";
input bool UseTrailingStop = true;
input int TSStart = 10;
input int TSStep = 10;
input int TSDistance = 15;
input bool TSEndBE = false;
input string Behavior = "--- EA Behavior ---------------";
input bool StealthMode = false;
extern bool OnlyCurrentPair = false;
string ShortName = "XP Trade Manager";
string ObjectSignature = "";
long chartID = 0;
const string nameProfitPips = "profitPips";
const string nameProfitCurrency = "profitCurrency";
int ordersHistoryCount=0;
struct HistoryStat
{
double profitPips;
double profitCurrency;
};
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
ShortName = WindowExpertName();
ObjectSignature = "["+ShortName+"]";
Print ("Init "+ShortName+" ver. "+Version);
if (StealthMode) OnlyCurrentPair = true;
chartID = ChartID();
ObjectCreate(chartID, nameProfitPips, OBJ_LABEL,0,0,0,0);
ObjectSetInteger(chartID, nameProfitPips, OBJPROP_XDISTANCE, 5);
ObjectSetInteger(chartID, nameProfitPips, OBJPROP_YDISTANCE, 20);
ObjectSetInteger(chartID, nameProfitPips, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
ObjectSetString(chartID, nameProfitPips, OBJPROP_TEXT, "Profit pips = 0");
ObjectCreate(chartID, nameProfitCurrency, OBJ_LABEL,0,0,0,0);
ObjectSetInteger(chartID, nameProfitCurrency, OBJPROP_XDISTANCE, 5);
ObjectSetInteger(chartID, nameProfitCurrency, OBJPROP_YDISTANCE, 35);
ObjectSetInteger(chartID, nameProfitCurrency, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
ObjectSetString(chartID, nameProfitCurrency, OBJPROP_TEXT, "Profit currency = 0,00 "+AccountCurrency());
ordersHistoryCount=0;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
ObjectDelete(chartID, nameProfitPips);
ObjectDelete(chartID, nameProfitCurrency);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
RefreshRates();
for (int i=OrdersTotal()-1; i>=0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if (!OnlyCurrentPair || OrderSymbol()==_Symbol)
{
double point = MarketInfo(OrderSymbol(), MODE_POINT);
int digits = (int)MarketInfo(OrderSymbol(), MODE_DIGITS);
if (digits==3 || digits==5) point *=10;
double slCurrentLevel = 0;
double tpCurrentLevel = 0;
bool closed = false;
double bid = MarketInfo(OrderSymbol(), MODE_BID);
double ask = MarketInfo(OrderSymbol(), MODE_ASK);
if (StealthMode)
{
slCurrentLevel = ObjectGet(ObjectSignature+"sl"+IntegerToString(OrderTicket()), OBJPROP_PRICE1);
tpCurrentLevel = ObjectGet(ObjectSignature+"tp"+IntegerToString(OrderTicket()), OBJPROP_PRICE1);
if (OrderType()==OP_BUY)
{
if (tpCurrentLevel > 0)
{
if (bid >= tpCurrentLevel)
{
closed = CloseOrder(OrderTicket());
}
}
if (slCurrentLevel > 0)
{
if (bid <= slCurrentLevel) closed = CloseOrder(OrderTicket());
}
}
else if (OrderType() == OP_SELL)
{
if (tpCurrentLevel > 0)
{
if (ask <= tpCurrentLevel) closed = CloseOrder(OrderTicket());
}
if (slCurrentLevel > 0)
{
if (ask >= slCurrentLevel) closed = CloseOrder(OrderTicket());
}
}
if (closed)
{
ObjectDelete(ObjectSignature+"sl"+IntegerToString(OrderTicket()));
ObjectDelete(ObjectSignature+"tp"+IntegerToString(OrderTicket()));
}
}
if (!closed)
{
// **************** check SL & TP *********************
if ((StopLoss > 0 || TakeProfit > 0) && ((!StealthMode && OrderStopLoss() == 0 && OrderTakeProfit() == 0) || (StealthMode && slCurrentLevel==0 && tpCurrentLevel==0)))
{
double stopLevel = MarketInfo(OrderSymbol(), MODE_STOPLEVEL)*point;
double distTP = MathMax(TakeProfit*point, stopLevel);
double distSL = MathMax(StopLoss*point, stopLevel);
double takeProfit = 0;
double stopLoss = 0;
if (OrderType() == OP_BUY)
{
if (TakeProfit > 0) takeProfit = OrderOpenPrice() + distTP;
if (StopLoss > 0) stopLoss = OrderOpenPrice() - distSL;
}
else if (OrderType() == OP_SELL)
{
if (TakeProfit > 0) takeProfit = OrderOpenPrice() - distTP;
if (StopLoss > 0) stopLoss = OrderOpenPrice() + distSL;
}
if (!StealthMode)
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopLoss, digits), NormalizeDouble(takeProfit, digits), OrderExpiration()))
Print(ShortName +" (OrderModify Error) "+ ErrorDescription(GetLastError()));
}
else
{
SetLevel(ObjectSignature+"sl"+IntegerToString(OrderTicket()), NormalizeDouble(stopLoss,digits), clrRed, STYLE_DASH, 1);
SetLevel(ObjectSignature+"tp"+IntegerToString(OrderTicket()), NormalizeDouble(takeProfit,digits), clrGreen, STYLE_DASH,1);
}
}
// ****** CHECK Trailing Stop && Break Even **************************
if (UseTrailingStop)
{
int priceDistance = 0;
int multi = 0;
double stopLoss=0;
double be;
if (OrderType() == OP_BUY)
{
priceDistance = (int)(NormalizeDouble(bid - OrderOpenPrice(), digits)/point);
if (priceDistance > TSStart)
{
multi = (int)MathFloor(priceDistance / TSStep);
if (multi > 0)
{
stopLoss = NormalizeDouble(OrderOpenPrice() + TSStep*multi*point, digits) - TSDistance*point;
if (TSEndBE)
{
be = NormalizeDouble(OrderOpenPrice() + BELevel*point, digits);
if (stopLoss > be) stopLoss = be;
}
}
if (!StealthMode)
{
if (NormalizeDouble(OrderStopLoss(), digits) < NormalizeDouble(stopLoss, digits))
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopLoss, digits), OrderTakeProfit(), OrderExpiration()))
Print(ShortName +" (OrderModify Error) "+ ErrorDescription(GetLastError()));
}
}
else
{
if (NormalizeDouble(slCurrentLevel, digits) < NormalizeDouble(stopLoss, digits)) SetLevel(ObjectSignature+"sl"+IntegerToString(OrderTicket()), NormalizeDouble(stopLoss,digits), clrRed, STYLE_DASH, 1);
}
}
}
else if (OrderType() == OP_SELL)
{
priceDistance = (int)(NormalizeDouble(OrderOpenPrice() - ask, digits)/point);
if (priceDistance > TSStart)
{
multi = (int)MathFloor(priceDistance / TSStep);
if (multi > 0)
{
stopLoss = NormalizeDouble(OrderOpenPrice() - TSStep*multi*point, digits) + TSDistance*point;
}
if (TSEndBE)
{
be = NormalizeDouble(OrderOpenPrice() - BELevel*point, digits);
if (stopLoss < be) stopLoss = be;
}
if (!StealthMode)
{
if (NormalizeDouble(OrderStopLoss(), digits) > NormalizeDouble(stopLoss, digits))
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopLoss, digits), OrderTakeProfit(), OrderExpiration()))
Print(ShortName +" (OrderModify Error) "+ ErrorDescription(GetLastError()));
}
}
else
{
if (NormalizeDouble(slCurrentLevel, digits) > NormalizeDouble(stopLoss, digits)) SetLevel(ObjectSignature+"sl"+IntegerToString(OrderTicket()), NormalizeDouble(stopLoss,digits), clrRed, STYLE_DASH, 1);
}
}
}
}
else if (UseBreakEven)
{
int slDistance = 0;
int priceDistance = 0;
double stopLoss=0;
if (OrderType() == OP_BUY)
{
slDistance = (int)(NormalizeDouble(OrderStopLoss() - OrderOpenPrice(),digits)/point);
if (slDistance < BELevel)
{
priceDistance = (int)(NormalizeDouble(bid - OrderOpenPrice(), digits)/point);
if (priceDistance >= BEActivation)
{
stopLoss = OrderOpenPrice() + BELevel*point;
if (!StealthMode)
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopLoss, digits), OrderTakeProfit(), OrderExpiration()))
Print(ShortName +" (OrderModify Error) "+ ErrorDescription(GetLastError()));
}
else
{
SetLevel(ObjectSignature+"sl"+IntegerToString(OrderTicket()), NormalizeDouble(stopLoss,digits), clrRed, STYLE_DASH, 1);
}
}
}
}
else if (OrderType() == OP_SELL)
{
slDistance = (int)(NormalizeDouble(OrderOpenPrice()-OrderStopLoss(), digits)/point);
if (slDistance < BELevel)
{
priceDistance = (int)(NormalizeDouble(OrderOpenPrice() - ask, digits)/point);
if (priceDistance >= BEActivation)
{
stopLoss = OrderOpenPrice() - BELevel*point;
if (!StealthMode)
{
if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopLoss, digits), OrderTakeProfit(), OrderExpiration()))
Print(ShortName +" (OrderModify Error) "+ ErrorDescription(GetLastError()));
}
else
{
SetLevel(ObjectSignature+"sl"+IntegerToString(OrderTicket()), NormalizeDouble(stopLoss,digits), clrRed, STYLE_DASH, 1);
}
}
}
}
}
}
}
}
}
if (OrdersHistoryTotal() != ordersHistoryCount)
{
// Refresh pips counter
HistoryStat histStat = {0,0};
ReadHistory(histStat);
ObjectSetString(chartID, nameProfitPips, OBJPROP_TEXT, "Profit pips = "+DoubleToStr(histStat.profitPips,0));
ObjectSetString(chartID, nameProfitCurrency, OBJPROP_TEXT, "Profit currency = "+DoubleToStr(histStat.profitCurrency,2)+" "+AccountCurrency());
ordersHistoryCount = OrdersHistoryTotal();
}
}
//+------------------------------------------------------------------+
//| Close Order |
//| PARAMS: int Ticket - ticket of closing order |
//+------------------------------------------------------------------+
bool CloseOrder(int Ticket)
{
datetime l_datetime = TimeCurrent();
bool closed = false;
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES))
{
l_datetime = TimeCurrent();
closed = false;
while(!closed && TimeCurrent() - l_datetime < 60)
{
closed = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, Gold);
int err = GetLastError();
if (err == 150) return (closed);
Sleep(1000);
while (IsTradeContextBusy()) Sleep(1000);
RefreshRates();
}
if (!closed) Print("OrderClose Error: "+ ErrorDescription(GetLastError()));
}
return (closed);
}
//+------------------------------------------------------------------+
//| Add or Update level line on chart |
//+------------------------------------------------------------------+
void SetLevel(string linename, double level, color col1, int linestyle, int thickness)
{
int digits= Digits;
// create or move the horizontal line
if (ObjectFind(linename) != 0) {
ObjectCreate(linename, OBJ_HLINE, 0, 0, level);
ObjectSet(linename, OBJPROP_STYLE, linestyle);
ObjectSet(linename, OBJPROP_COLOR, col1);
ObjectSet(linename, OBJPROP_WIDTH, thickness);
ObjectSet(linename, OBJPROP_BACK, True);
}
else
{
ObjectMove(linename, 0, Time[0], level);
}
}
void RemoveLines()
{
int obj_total= ObjectsTotal();
int signatureLength = StringLen(ObjectSignature);
for (int i= obj_total; i>=0; i--) {
string name= ObjectName(i);
if (StringSubstr(name,0,signatureLength)==ObjectSignature) ObjectDelete(name);
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Read stat from history |
//+------------------------------------------------------------------+
bool ReadHistory(HistoryStat &stat)
{
stat.profitPips=0;
stat.profitCurrency=0;
datetime day = StringToTime(TimeToString(TimeCurrent(), TIME_DATE));
int i=OrdersHistoryTotal()-1;
while (i >=0 )
{
if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if (!OnlyCurrentPair || OrderSymbol()==_Symbol){
if(OrderCloseTime()>=day){
double point = MarketInfo(OrderSymbol(), MODE_POINT);
int digits = (int)MarketInfo(OrderSymbol(), MODE_DIGITS);
if (digits==3 || digits==5) point *=10;
stat.profitPips += MathAbs(OrderClosePrice()-OrderOpenPrice())/point;
stat.profitCurrency += OrderProfit()+OrderCommission()+OrderSwap();
}
}
}
i--;
}
return (true);
}
Comments