ÿþ
#property copyright "Abraão Moreira"
#property link "abraaomoreira.com"
#property version "3.4"
#include <Trade/Trade.mqh>
CTrade trade;
enum options {
yes = 1,
no = 0,
};
input double TP = 100;
input double SL = 100;
input double settedVolume = 1;
input bool trailingStopSwitch = true;
input bool breakevenSwitch = true;
input bool martingaleSwitch = true;
input bool manualFirstSwitch = true;
input bool againstTrendSwitch = false;
input int maxMartingales = 5;
input double martingaleFactor = 2;
input double maxLoss = 1000;
input double maxProfit = 1000;
input options operationalTimeControl = yes;
input string begin = "09:00";
input string finish = "17:30";
string today;
int contMartingales = 0;
double pastClose = iClose(NULL, 0, 1);
int OnInit() {
MessageBox("Please, check the configurations applied to the current stock, a wrong config can impede EA works!!! \n\n Thanks for download, enjoy.",
NULL,
MB_ICONINFORMATION);
today = TimeToString(TimeLocal(), TIME_DATE);
VolumesOk(settedVolume);
InTimeInterval(begin, finish, operationalTimeControl, true);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
}
void OnTick() {
double bid, ask;
ulong lastTicket, pastTicket;
uint dealsTotal;
string orderControl;
PositionSelect(_Symbol);
lastTicket = PositionGetInteger(POSITION_TICKET);
HistorySelect(StringToTime(today), TimeLocal());
dealsTotal = HistoryDealsTotal();
pastTicket = HistoryDealGetTicket(dealsTotal-1);
TimeLimit(finish, INT_MAX, operationalTimeControl);
ProfitReached(maxProfit, StringToTime(today), TimeLocal());
LossReached(maxLoss, StringToTime(today), TimeLocal());
orderControl = OperationStrategy();
ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
if(manualFirstSwitch) {
if(breakevenSwitch && trailingStopSwitch)
TrailingStop(!trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
else
TrailingStop(trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
Breakeven(breakevenSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
if(contMartingales <= maxMartingales &&
HistoryDealGetDouble(pastTicket, DEAL_PROFIT) < 0 &&
OrderSendRequirements()) {
if(orderControl == "BUY")
Martingale(martingaleSwitch, martingaleFactor, orderControl, ask, SL, TP);
if(orderControl == "SELL")
Martingale(martingaleSwitch, martingaleFactor, orderControl, bid, SL, TP);
contMartingales++;
}
} else {
if(PositionGetInteger(POSITION_REASON) == POSITION_REASON_EXPERT) {
if(breakevenSwitch && trailingStopSwitch)
TrailingStop(!trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
else
TrailingStop(trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
Breakeven(breakevenSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
}
if(contMartingales < maxMartingales &&
HistoryDealGetDouble(pastTicket, DEAL_PROFIT) <= 0 &&
OrderSendRequirements()) {
if(orderControl == "BUY")
Martingale(martingaleSwitch, martingaleFactor, orderControl, ask, SL, TP);
if(orderControl == "SELL")
Martingale(martingaleSwitch, martingaleFactor, orderControl, bid, SL, TP);
contMartingales++;
} else
AutomaticOrder(orderControl);
}
if(HistoryDealGetDouble(pastTicket, DEAL_PROFIT) > 0)
contMartingales = 0;
}
string OperationStrategy() {
if(againstTrendSwitch) {
if(iClose(NULL, 0, 1) < iOpen(NULL, 0, 1))
return "BUY";
if(iClose(NULL, 0, 1) > iOpen(NULL, 0, 1))
return "SELL";
} else {
if(iClose(NULL, 0, 1) < iOpen(NULL, 0, 1))
return "SELL";
if(iClose(NULL, 0, 1) > iOpen(NULL, 0, 1))
return "BUY";
}
return "-";
}
void AutomaticOrder(string orderControl) {
double ask, bid;
ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
if(orderControl == "BUY" &&
OrderSendRequirements()) {
trade.Buy(settedVolume, NULL, ask, ask - SL*_Point, ask + TP*_Point);
}
if(orderControl == "SELL" &&
OrderSendRequirements()) {
trade.Sell(settedVolume, NULL, bid, bid + SL*_Point, bid - TP*_Point);
}
}
bool NewCandle() {
if(pastClose != iClose(NULL, 0, 1)) {
pastClose = iClose(NULL, 0, 1);
return true;
}
pastClose = iClose(NULL, 0, 1);
return false;
}
bool OrderSendRequirements() {
if(VolumesOk(settedVolume) &&
InTimeInterval(begin, finish, operationalTimeControl, false) &&
NewCandle() &&
!ProfitReached(maxProfit, StringToTime(today), TimeLocal()) &&
!LossReached(maxLoss, StringToTime(today), TimeLocal()) &&
!PositionSelect(_Symbol))
return true;
return false;
}
bool InTimeInterval(string begin_,
string finish_,
bool control,
bool showMessage) {
if(!control)
return true;
if(begin_ <= TimeToString(TimeLocal(), TIME_MINUTES) &&
TimeToString(TimeLocal(), TIME_MINUTES) <= finish_)
return true;
if(showMessage)
MessageBox("Out of operational time interval setted. \n\n" +
begin_ + " - " + finish_
+ "\n\nPlease, change the configurations!");
return false;
}
void TimeLimit(string finish_,
int deviation,
bool control) {
if((TimeToString(TimeLocal(), TIME_MINUTES) >= finish_) && control) {
CloseAllPositions(deviation);
}
}
bool IsOperationDay(int &daysOn[]) {
MqlDateTime strTimeLocal;
TimeToStruct(TimeLocal(), strTimeLocal);
for(int i = 0; i < ArraySize(daysOn); i++)
if(strTimeLocal.day_of_week == daysOn[i])
return true;
return false;
}
bool ProfitReached(double profitMax_PR,
datetime initDate_PR,
datetime finishDate_PR) {
double acum = AcumulatedProfit(initDate_PR, finishDate_PR);
if(AcumulatedProfit(initDate_PR, finishDate_PR) >= profitMax_PR) {
CloseAllPositions(INT_MAX);
MessageBox("Diary monetary profit reached: \n" + (string)profitMax_PR);
return true;
}
return false;
}
bool LossReached(double lossMax_LR,
datetime initDate,
datetime finishDate) {
if(AcumulatedProfit(initDate, finishDate) <= (lossMax_LR * -1)) {
CloseAllPositions(INT_MAX);
MessageBox("Diary monetary loss reached: \n" + (string)lossMax_LR);
return true;
}
return false;
}
double AcumulatedProfit(datetime initDate_AP,
datetime finishDate_AP) {
double profitAcum = 0;
HistorySelect(initDate_AP, finishDate_AP);
for(int i = 1; i <= HistoryDealsTotal(); i++) {
ulong ticket = HistoryDealGetTicket(i);
profitAcum += HistoryDealGetDouble(ticket, DEAL_PROFIT);
}
return profitAcum;
}
void CloseAllPositions(int deviation) {
CTrade trade_TL;
ulong ticket = 0;
if(PositionSelect(_Symbol)) {
for(int i = 0; i < PositionsTotal(); i++) {
ticket = PositionGetTicket(i);
trade_TL.PositionClose(ticket, deviation);
}
}
}
void TrailingStop (bool control,
ulong ticket,
double stopLoss,
double step) {
CTrade trade_TS;
double newSL = 0;
if(PositionSelectByTicket(ticket) &&
PositionGetDouble(POSITION_PROFIT) > 0 &&
control) {
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
newSL = PositionGetDouble(POSITION_PRICE_CURRENT) - stopLoss;
if(newSL > PositionGetDouble(POSITION_SL))
trade_TS.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP));
}
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
newSL = PositionGetDouble(POSITION_PRICE_CURRENT) + stopLoss;
if(newSL < PositionGetDouble(POSITION_SL))
trade_TS.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP));
}
}
}
void Breakeven (bool control,
ulong ticket,
double stopLoss,
double step) {
bool trailingControl = true;
if(control &&
PositionSelectByTicket(ticket)) {
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
if(PositionGetDouble(POSITION_SL) >= PositionGetDouble(POSITION_PRICE_OPEN))
trailingControl = false;
} else {
if(PositionGetDouble(POSITION_SL) <= PositionGetDouble(POSITION_PRICE_OPEN))
trailingControl = false;
}
TrailingStop(trailingControl, ticket, stopLoss, step);
}
}
double Martingale (bool control,
double factor,
string type,
double operationPrice,
double stopLoss,
double takeProfit) {
CTrade trade_M;
ulong ticket;
uint total = 0;
double lastVolume = 0, newVolume = 0;
if(control){
HistorySelect(0, TimeLocal());
total = HistoryDealsTotal();
ticket = HistoryDealGetTicket(total-1);
lastVolume = HistoryDealGetDouble(ticket, DEAL_VOLUME);
HistoryDealGetInteger(ticket, DEAL_TYPE);
newVolume = lastVolume * factor;
if(type == "BUY")
trade_M.Buy(newVolume,
_Symbol,
operationPrice,
operationPrice - stopLoss*_Point,
operationPrice + takeProfit*_Point);
if(type == "SELL")
trade_M.Sell(newVolume,
_Symbol,
operationPrice,
operationPrice + stopLoss*_Point,
operationPrice - takeProfit*_Point);
}
return newVolume;
}
bool VolumesOk(double volume) {
double min_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double max_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double volume_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(volume < min_volume) {
MessageBox("Volume is less than the minimal to this symbol! \n" + "Minimal volume: " + (string)min_volume + "\n \n Please, try again with different value.");
return false;
}
if(volume > max_volume) {
MessageBox("Volume is greater than the maximal to this symbol! \n" + "Maximal volume: " + (string)max_volume + "\n \n Please, try again with different value.");
return false;
}
int ratio = (int)MathRound(volume/volume_step);
if(MathAbs(ratio*volume_step - volume) > 0.0000001) {
MessageBox("Volume is not a multiple of the minimal step to this symbol!\n" + "Minimal step: " + (string)volume_step + "\n \n Please, try again with different value.");
return false;
}
return true;
}
Comments