mql5/Experts/Downloads/BollingerBandsEA_Ver3.0.mq5

827 lines
61 KiB
MQL5

2025-08-10 17:43:21 -04:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| BollingerBandsEA.mq5 |
//| Copyright 2024, Igor Widiger |
//| https://www.mql5.com/en/users/deinschanz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Igor Widiger"
#property link "https://www.mql5.com/en/users/deinschanz"
#property version "3.00"
#property description "Update: The positions will only be opened after the bearish or bullish candle."
#property description "Indicators such as Moving Average and Bollinger Bands removed from the chat after closing the EA."
#property description "Small errors with closing the positions after time."
input group "---------- General ----------"
input ulong Magic = 111111111111; // Magic number
input group "---------- Risk- and Moneymanagement ----------"
enum my_lots {
fixed_volume = 1, // Fixed volume
procent_volume = 2, // Procent volume
};
input my_lots volumetype = procent_volume; // Volume type
input double Risk = 1; // Risk for Position
input double Lots = 0.10; // Lots
input int Stopp = 100; // Stoploss in points
input group "---------- Session start - and end ----------"
input int MinutesAfterSessionStart = 420; // Trading (minutes) begins after session start
input int MinutesBeforSessionStart = 5; // Trading (minutes) end before session
input group "---------- Close positions ----------"
input bool ClosePos = false; // Close position after indicator
input bool Trall = true; // Allow trailing stop?
input int ProfitFactor = 2; // Profit factor (RR) after stop is pulled
input bool Break = false; // Allow breakeven?
input int ProfitFactor2 = 1; // Profit factor (RR) after stop is pulled
input int ClosePosMinutes = 30; // Close position if it is in minus (after minutes)
#include <Trade/Trade.mqh>
#include <Trade/SymbolInfo.mqh>
int handleBp, handleMa;
static datetime timestamp;
static double lot = 0;
CTrade trade;
CSymbolInfo m_symbol;
CPositionInfo m_position;
CHistoryOrderInfo m_history;
CDealInfo m_deal;
int OnInit() {
handleBp = iBands(_Symbol,PERIOD_CURRENT,20,0,2.000,PRICE_CLOSE);
handleMa = iMA(_Symbol,PERIOD_D1,100,0,MODE_SMA,PRICE_CLOSE);
//---
trade.SetExpertMagicNumber(Magic);
//---
trade.SetMarginMode();
trade.SetTypeFillingBySymbol(m_symbol.Name());
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
ActionsOnTheChart(0);
}
void OnTick() {
// Sessioncheck
if(IsInTradingSession(_Symbol) == false) return;
int bars = iBars(_Symbol,PERIOD_CURRENT);
datetime time = iTime(_Symbol,PERIOD_CURRENT,0);
double DayHigh = iHigh(NULL,PERIOD_D1,0); // Day High Period
double DayLow = iLow(NULL,PERIOD_D1,0); // Day Low Period
double DayHigh1 = iHigh(NULL,PERIOD_D1,1); // Day High Period
double DayLow1 = iLow(NULL,PERIOD_D1,1); // Day Low Period
double DayHighPrice = 0;
double DayLowPrice = 0;
double DayHighPrice1 = 0;
double DayLowPrice1 = 0;
if(timestamp != time) {
timestamp = time;
DayHighPrice = DayHigh;
DayLowPrice = DayLow;
DayHighPrice1 = DayHigh1;
DayLowPrice1 = DayLow1;
}
double close1 = iClose(_Symbol,PERIOD_CURRENT,1); // Close candle 1
double open1 = iOpen(_Symbol,PERIOD_CURRENT,1); // Open candle 1
double high1 = iHigh(_Symbol,PERIOD_CURRENT,1); // High candle 1
double low1 = iLow(_Symbol,PERIOD_CURRENT,1); // Low candle 1
double high0 = iHigh(_Symbol,PERIOD_CURRENT,0); // High cadle current
double low0 = iLow(_Symbol,PERIOD_CURRENT,0); // Low candle current
double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
ask = NormalizeDouble(ask,_Digits);
double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
bid = NormalizeDouble(bid,_Digits);
double bbUpper[], bbLowwer[], bbMiddle[];
CopyBuffer(handleBp,BASE_LINE,1,2,bbMiddle);
CopyBuffer(handleBp,UPPER_BAND,1,2,bbUpper);
CopyBuffer(handleBp,LOWER_BAND,1,2,bbLowwer);
// Range middle upper and lowwer line
double rangeUpper = (bbUpper[1] - bbMiddle[1])/_Point;
double rangeLowwer = (bbMiddle[1] -bbLowwer[1])/_Point;
// Ma indikator
double ma[];
CopyBuffer(handleMa,MAIN_LINE,1,1,ma);
// Close position after indicator
if(ClosePos == true) {
for(int i=PositionsTotal()-1; i>=0; i--) // Returns the number of open positions
if(m_position.SelectByIndex(i)) {
//---
if(m_position.Symbol()== _Symbol && m_position.Magic()==Magic) { // Checks for symbol and magic number
if(m_position.PositionType()==POSITION_TYPE_BUY) {
if(bid >= bbMiddle[0]) {
ClosePosByTime(_Symbol);
}
} else {
if(ask <= bbMiddle[0]) {
ClosePosByTime(_Symbol);
}
}
}
}
}
// Trailingstop
if(Trall == true) {
Trailing(_Symbol);
}
// Breakeven
if(Break == true) {
Breakeven(_Symbol);
}
// End trade after time if order is positiv
datetime AktZeit=TimeCurrent();
HistorySelect(0,TimeCurrent());
for(int pos=HistoryDealsTotal()-1; pos>=0; pos--) {
if(m_position.SelectByIndex(pos)) {
// Read deal out and get deal time
if(m_position.Symbol()==_Symbol && m_position.Magic()==Magic) {
datetime close_time = m_position.Time();
datetime adierentime = close_time + (ClosePosMinutes*60);
if(AktZeit >= adierentime && AProfit() < 0) {
ClosePosByTime(_Symbol);
return;
}
}
}
}
// Start trading for profit the next day!
if(Profit(0) > 0) {
return;
}
if(CalculateOnePositions(_Symbol) >= 1)
return;
if(open1 > close1 && close1 > bbUpper[1] && bid > bbUpper[1] && rangeUpper > Stopp*2 && ask < ma[0]) {
if(bid > DayHighPrice || bid > DayHighPrice1) {
if(ProfitSell(0) < 0) return;
double newSl = 0;
if(high1 > high0) {
newSl = high1;
} else if(high1 < high0) {
newSl = high0;
} else {
return; // Kein Trade
}
double sl = newSl + Stopp*_Point;
double tp = DayLow;
// Calculate SL in points
double Points = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double SlPoints = (sl - ask) / _Point;
if(volumetype == 2) {
lot = NormalizeDouble(LotsByRisk(ORDER_TYPE_SELL,Risk,(int)SlPoints,_Symbol,Points),2);
} else {
lot= Lots;
}
double volume = lot;
volume=LotCheck(volume, _Symbol);
if(volume==0)
return;
if(!CheckStopLoss_Takeprofit(ORDER_TYPE_SELL,sl,tp)) {
return;
}
double max_volume=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_LIMIT);
double current_lots=getAllVolume();
if(max_volume>0 && max_volume-volume<=0) {
return;
}
trade.Sell(volume,_Symbol,bid,sl,tp);
}
} else if(close1 > open1 && close1 < bbLowwer[1] && ask < bbLowwer[1] && rangeLowwer > Stopp*2 && bid > ma[0]) {
if(ask < DayLowPrice || ask < DayLowPrice1) {
if(ProfitBuy(0) < 0) return;
double newSl = 0;
if(low1 > low0) {
newSl = low0;
} else if(low1 < low0) {
newSl = low1;
} else {
return; // Kein Trade
}
double sl = newSl - Stopp*_Point;
double tp = DayHigh;
// Calculate SL in points
double Points = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double SlPoints = (bid - sl)/_Point;
if(volumetype == 2) {
lot = NormalizeDouble(LotsByRisk(ORDER_TYPE_BUY,Risk,(int)SlPoints,_Symbol,Points),2);
} else {
lot= Lots;
}
double volume = lot;
volume=LotCheck(volume, _Symbol);
if(volume==0)
return;
if(!CheckStopLoss_Takeprofit(ORDER_TYPE_BUY,sl,tp)) {
return;
}
double max_volume=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_LIMIT);
double current_lots=getAllVolume();
if(max_volume>0 && max_volume-volume<=0) {
return;
}
trade.Buy(volume,_Symbol,ask,sl,tp);
}
}
}
//+------------------------------------------------------------------+
//| Calculate one positions |
//+------------------------------------------------------------------+
int CalculateOnePositions(string ssymBol) {
int total=0;
for(int i=PositionsTotal()-1; i>=0; i--)
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
if(m_position.Symbol() == ssymBol && m_position.Magic()==Magic) { // Checks by magic number end Symbol
total++;
//---
}
return(total);
}
//+------------------------------------------------------------------+
// Close position function
void ClosePosByTime(string symbolss) {
for(int i=PositionsTotal()-1; i>=0; i--)
if(m_position.SelectByIndex(i))
if(m_position.Symbol()== _Symbol && m_position.Magic()==Magic) { // Checks by symbol and magic number
trade.PositionClose(m_position.Ticket());
}
}
//------------- Profit sell ausrechnen Funktion ---------------------------
double ProfitSell(int ai_0) {
// HistorySelect(von_datum,zum_datum);
HistorySelect(iTime(_Symbol,PERIOD_D1,ai_0),iTime(_Symbol,PERIOD_D1,ai_0)+60*60*24);
double gewonnene_trade=0.0;
double verlorene_trade=0.0;
double total_profit=0.0;
uint total=HistoryDealsTotal();
ulong ticket=0;
//--- for all deals
for(uint i=0; i<total; i++) {
//--- Sucht nach Tickets die gr<EFBFBD>sser als Null sind
if((ticket=HistoryDealGetTicket(i))>0) {
long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
if(entry==DEAL_ENTRY_IN)
continue;
string symbol = HistoryDealGetString(ticket,DEAL_SYMBOL);
long order_magic = HistoryDealGetInteger(ticket,DEAL_MAGIC);
double deal_commission = HistoryDealGetDouble(ticket,DEAL_COMMISSION);
double deal_swap = HistoryDealGetDouble(ticket,DEAL_SWAP);
double deal_profit = HistoryDealGetDouble(ticket,DEAL_PROFIT);
double profit=deal_commission+deal_swap+deal_profit;
ENUM_DEAL_TYPE deal_type= (ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket, DEAL_TYPE);
long dreason= (int)HistoryDealGetInteger(ticket,DEAL_REASON);
if(deal_type!=DEAL_TYPE_BUY)
continue;
if(order_magic==Magic) {
//... processing of deal with some DEAL_MAGIC
if(symbol==_Symbol && dreason==(DEAL_REASON_SL)) {
if(profit<0.0)
verlorene_trade+=profit;
total_profit+=profit;
}
}
}
}
return(total_profit);
}
//------------- Profit sell ausrechnen Funktion ---------------------------
double ProfitBuy(int ai_0) {
// HistorySelect(von_datum,zum_datum);
HistorySelect(iTime(_Symbol,PERIOD_D1,ai_0),iTime(_Symbol,PERIOD_D1,ai_0)+60*60*24);
double gewonnene_trade=0.0;
double verlorene_trade=0.0;
double total_profit=0.0;
uint total=HistoryDealsTotal();
ulong ticket=0;
//--- for all deals
for(uint i=0; i<total; i++) {
//--- Searches for tickets greater than zero
if((ticket=HistoryDealGetTicket(i))>0) {
long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
if(entry==DEAL_ENTRY_IN)
continue;
string symbol = HistoryDealGetString(ticket,DEAL_SYMBOL);
long order_magic = HistoryDealGetInteger(ticket,DEAL_MAGIC);
double deal_commission = HistoryDealGetDouble(ticket,DEAL_COMMISSION);
double deal_swap = HistoryDealGetDouble(ticket,DEAL_SWAP);
double deal_profit = HistoryDealGetDouble(ticket,DEAL_PROFIT);
double profit=deal_commission+deal_swap+deal_profit;
ENUM_DEAL_TYPE deal_type= (ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket, DEAL_TYPE);
if(deal_type!=DEAL_TYPE_SELL)
continue;
long dreason= (int)HistoryDealGetInteger(ticket,DEAL_REASON);
if(order_magic==Magic) {
//... processing of deal with some DEAL_MAGIC
if(symbol==_Symbol && dreason==(DEAL_REASON_SL)) {
if(profit<0.0)
verlorene_trade+=profit;
total_profit+=profit;
}
}
}
}
return(total_profit);
}
//------------- Profit ausrechnen Funktion ---------------------------
double Profit(int ai_0) {
// HistorySelect(von_datum,zum_datum);
HistorySelect(iTime(_Symbol,PERIOD_D1,ai_0),iTime(_Symbol,PERIOD_D1,ai_0)+60*60*24);
double gewonnene_trade=0.0;
double verlorene_trade=0.0;
double total_profit=0.0;
uint total=HistoryDealsTotal();
ulong ticket=0;
//--- for all deals
for(uint i=0; i<total; i++) {
//--- Sucht nach Tickets die gr<EFBFBD>sser als Null sind