Untitled
unknown
plain_text
3 years ago
22 kB
11
Indexable
//
// EA Studio Expert Advisor
//
// Created with: Expert Advisor Studio
// Website: https://eas.forexsb.com
//
// Copyright 2023, Forex Software Ltd.
//
// Risk Disclosure
//
// Futures and forex trading contains substantial risk and is not for every investor.
// An investor could potentially lose all or more than the initial investment.
// Risk capital is money that can be lost without jeopardizing ones’ financial security or life style.
// Only risk capital should be used for trading and only those with sufficient risk capital should consider trading.
#property copyright "Forex Software Ltd."
#property version "3.3"
#property strict
extern double MONTO = 1000; // Saldo inicial de la cuenta
extern int Maxima_Perdida_Diaria = 5; // Porcentaje máximo de pérdida diaria permitido
static input string _Properties_ = "------"; // --- Expert Properties ---
static input double Entry_Amount = 0.47; // Entry lots
input int Stop_Loss = 5; // Stop Loss (pips)
input int Take_Profit = 0; // Take Profit (pips)
static input string ___0______ = "------"; // --- Bollinger Bands ---
input int Ind0Param0 = 5; // Period
input double Ind0Param1 = 2.92; // Deviation
static input string ___1______ = "------"; // --- Moving Averages Crossover ---
input int Ind1Param0 = 14; // Fast MA period
input int Ind1Param1 = 31; // Slow MA period
static input string _Settings___ = "------"; // --- Expert Settings ---
static input int Magic_Number = 53832080; // Magic Number
#define TRADE_RETRY_COUNT 4
#define TRADE_RETRY_WAIT 100
#define OP_FLAT -1
// Session time is set in seconds from 00:00
int sessionSundayOpen = 0; // 00:00
int sessionSundayClose = 86400; // 24:00
int sessionMondayThursdayOpen = 3600; // 01:00
int sessionMondayThursdayClose = 79200; // 22:00
int sessionFridayOpen = 3600; // 01:00
int sessionFridayClose = 79200; // 22:00
bool sessionIgnoreSunday = false;
bool sessionCloseAtSessionClose = false;
bool sessionCloseAtFridayClose = true;
const double sigma = 0.000001;
const int requiredBars = 33;
double posType = OP_FLAT;
int posTicket = 0;
double posLots = 0;
double posStopLoss = 0;
double posTakeProfit = 0;
datetime barTime;
double pip;
double stopLevel;
bool isTrailingStop = true;
bool setProtectionSeparately = false;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
barTime = Time[0];
stopLevel = MarketInfo(_Symbol, MODE_STOPLEVEL);
pip = GetPipValue();
isTrailingStop = isTrailingStop && Stop_Loss > 0;
return ValidateInit();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTick()
{
if (ArraySize(Time) < requiredBars)
return;
if (Time[0] > barTime)
{
barTime = Time[0];
OnBar();
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnBar()
{
UpdatePosition();
if (posType != OP_FLAT && IsForceSessionClose())
{
ClosePosition();
return;
}
if ( IsOutOfSession() )
return;
if (posType != OP_FLAT)
{
ManageClose();
UpdatePosition();
}
if (posType != OP_FLAT && isTrailingStop)
{
double trailingStop = GetTrailingStopPrice();
ManageTrailingStop(trailingStop);
UpdatePosition();
}
int entrySignal = GetEntrySignal();
if ((posType == OP_BUY && entrySignal == OP_SELL) ||
(posType == OP_SELL && entrySignal == OP_BUY ))
{
ClosePosition();
// Hack to prevent MT bug https://forexsb.com/forum/post/73434/#p73434
int repeatCount = 80;
int delay = 50;
for (int i = 0; i < repeatCount; i++)
{
UpdatePosition();
if (posType == OP_FLAT) break;
Sleep(delay);
}
}
if (posType == OP_FLAT && entrySignal != OP_FLAT)
{
OpenPosition(entrySignal);
UpdatePosition();
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void UpdatePosition()
{
posType = OP_FLAT;
posTicket = 0;
posLots = 0;
int total = OrdersTotal();
for (int pos = total - 1; pos >= 0; pos--)
{
if (OrderSelect(pos, SELECT_BY_POS) &&
OrderSymbol() == _Symbol &&
OrderMagicNumber() == Magic_Number)
{
posType = OrderType();
posLots = OrderLots();
posTicket = OrderTicket();
posStopLoss = OrderStopLoss();
posTakeProfit = OrderTakeProfit();
break;
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int GetEntrySignal()
{
// Bollinger Bands (Close, 5, 2.92)
double ind0upBand1 = iBands(NULL, 0, Ind0Param0, Ind0Param1, 0, PRICE_CLOSE, MODE_UPPER, 1);
double ind0dnBand1 = iBands(NULL, 0, Ind0Param0, Ind0Param1, 0, PRICE_CLOSE, MODE_LOWER, 1);
double ind0upBand2 = iBands(NULL, 0, Ind0Param0, Ind0Param1, 0, PRICE_CLOSE, MODE_UPPER, 2);
double ind0dnBand2 = iBands(NULL, 0, Ind0Param0, Ind0Param1, 0, PRICE_CLOSE, MODE_LOWER, 2);
bool ind0long = Open(0) < ind0dnBand1 - sigma && Open(1) > ind0dnBand2 + sigma;
bool ind0short = Open(0) > ind0upBand1 + sigma && Open(1) < ind0upBand2 - sigma;
bool canOpenLong = ind0long;
bool canOpenShort = false;
return canOpenLong && !canOpenShort ? OP_BUY
: canOpenShort && !canOpenLong ? OP_SELL
: OP_FLAT;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ManageClose()
{
// Moving Averages Crossover (Smoothed, Simple, 14, 31)
double ind1val1 = iMA(NULL, 0, Ind1Param0, 0, MODE_SMMA, PRICE_CLOSE, 1);
double ind1val2 = iMA(NULL, 0, Ind1Param1, 0, MODE_SMA, PRICE_CLOSE, 1);
double ind1val3 = iMA(NULL, 0, Ind1Param0, 0, MODE_SMMA, PRICE_CLOSE, 2);
double ind1val4 = iMA(NULL, 0, Ind1Param1, 0, MODE_SMA, PRICE_CLOSE, 2);
bool ind1long = ind1val1 > ind1val2 + sigma && ind1val3 < ind1val4 - sigma;
bool ind1short = ind1val1 < ind1val2 - sigma && ind1val3 > ind1val4 + sigma;
if ( (posType == OP_BUY && ind1long) ||
(posType == OP_SELL && ind1short) )
ClosePosition();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OpenPosition(int command)
{
double equity = AccountInfoDouble(ACCOUNT_EQUITY); // Get the equity value of the account
double max_loss = (AccountInfoDouble(ACCOUNT_BALANCE) * Maxima_Perdida_Diaria / 100); // Calculate the maximum daily loss
if (equity < max_loss) // Check if equity loss is greater than the maximum daily loss
{
CloseAllOrders(); // Close all open orders
}
for (int attempt = 0; attempt < TRADE_RETRY_COUNT; attempt++)
{
int ticket = 0;
int lastError = 0;
bool modified = false;
string comment = IntegerToString(Magic_Number);
color arrowColor = command == OP_BUY ? clrGreen : clrRed;
if (IsTradeContextFree())
{
double price = command == OP_BUY ? Ask() : Bid();
double stopLoss = GetStopLossPrice(command);
double takeProfit = GetTakeProfitPrice(command);
if (setProtectionSeparately)
{
// Send an entry order without SL and TP
ticket = OrderSend(_Symbol, command, Entry_Amount, price, 10, 0, 0, comment, Magic_Number, 0, arrowColor);
// If the order is successful, modify the position with the corresponding SL and TP
if (ticket > 0 && (Stop_Loss > 0 || Take_Profit > 0))
modified = OrderModify(ticket, 0, stopLoss, takeProfit, 0, clrBlue);
}
else
{
// Send an entry order with SL and TP
ticket = OrderSend(_Symbol, command, Entry_Amount, price, 10, stopLoss, takeProfit, comment, Magic_Number, 0, arrowColor);
lastError = GetLastError();
// If order fails, check if it is because inability to set SL or TP
if (ticket <= 0 && lastError == 130)
{
// Send an entry order without SL and TP
ticket = OrderSend(_Symbol, command, Entry_Amount, price, 10, 0, 0, comment, Magic_Number, 0, arrowColor);
// Try setting SL and TP
if (ticket > 0 && (Stop_Loss > 0 || Take_Profit > 0))
modified = OrderModify(ticket, 0, stopLoss, takeProfit, 0, clrBlue);
// Mark the expert to set SL and TP with a separate order
if (ticket > 0 && modified)
{
setProtectionSeparately = true;
Print("Detected ECN type position protection.");
}
}
}
}
if (ticket > 0)
break;
lastError = GetLastError();
if (lastError != 135 && lastError != 136 && lastError != 137 && lastError != 138)
break;
Sleep(TRADE_RETRY_WAIT);
Print("Open Position retry no: " + IntegerToString(attempt + 2));
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ClosePosition()
{
for(int attempt = 0; attempt < TRADE_RETRY_COUNT; attempt++)
{
bool closed;
int lastError = 0;
if ( IsTradeContextFree() )
{
double price = posType == OP_BUY ? Bid() : Ask();
closed = OrderClose(posTicket, posLots, price, 10, clrYellow);
lastError = GetLastError();
}
if (closed)
break;
if (lastError == 4108)
break;
Sleep(TRADE_RETRY_WAIT);
Print("Close Position retry no: " + IntegerToString(attempt + 2));
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ModifyPosition()
{
for (int attempt = 0; attempt < TRADE_RETRY_COUNT; attempt++)
{
bool modified;
int lastError = 0;
if ( IsTradeContextFree() )
{
modified = OrderModify(posTicket, 0, posStopLoss, posTakeProfit, 0, clrBlue);
lastError = GetLastError();
}
if (modified)
break;
if (lastError == 4108)
break;
Sleep(TRADE_RETRY_WAIT);
Print("Modify Position retry no: " + IntegerToString(attempt + 2));
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double GetStopLossPrice(int command)
{
if (Stop_Loss == 0)
return 0;
double delta = MathMax(pip * Stop_Loss, _Point * stopLevel);
double stopLoss = command == OP_BUY ? Bid() - delta : Ask() + delta;
return NormalizeDouble(stopLoss, _Digits);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double GetTakeProfitPrice(int command)
{
if (Take_Profit == 0)
return 0;
double delta = MathMax(pip * Take_Profit, _Point * stopLevel);
double takeProfit = command == OP_BUY ? Bid() + delta : Ask() - delta;
return NormalizeDouble(takeProfit, _Digits);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double GetTrailingStopPrice()
{
double bid = Bid();
double ask = Ask();
double spread = ask - bid;
double stopLevelPoints = _Point * stopLevel;
double stopLossPoints = pip * Stop_Loss;
if (posType == OP_BUY)
{
double newStopLoss = High(1) - stopLossPoints;
if (posStopLoss <= newStopLoss - pip)
return newStopLoss < bid
? newStopLoss >= bid - stopLevelPoints
? bid - stopLevelPoints
: newStopLoss
: bid;
}
if (posType == OP_SELL)
{
double newStopLoss = Low(1) + spread + stopLossPoints;
if (posStopLoss >= newStopLoss + pip)
return newStopLoss > ask
? newStopLoss <= ask + stopLevelPoints
? ask + stopLevelPoints
: newStopLoss
: ask;
}
return posStopLoss;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ManageTrailingStop(double trailingStop)
{
if ( (posType == OP_BUY && MathAbs(trailingStop - Bid()) < _Point) ||
(posType == OP_SELL && MathAbs(trailingStop - Ask()) < _Point) )
{
ClosePosition();
return;
}
if ( MathAbs(trailingStop - posStopLoss) > _Point )
{
posStopLoss = NormalizeDouble(trailingStop, _Digits);
ModifyPosition();
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double Bid()
{
return MarketInfo(_Symbol, MODE_BID);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double Ask()
{
return MarketInfo(_Symbol, MODE_ASK);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
datetime Time(int bar)
{
return Time[bar];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double Open(int bar)
{
return Open[bar];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double High(int bar)
{
return High[bar];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double Low(int bar)
{
return Low[bar];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double Close(int bar)
{
return Close[bar];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double GetPipValue()
{
return _Digits == 4 || _Digits == 5 ? 0.0001
: _Digits == 2 || _Digits == 3 ? 0.01
: _Digits == 1 ? 0.1 : 1;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsTradeContextFree()
{
if ( IsTradeAllowed() )
return true;
uint startWait = GetTickCount();
Print("Trade context is busy! Waiting...");
while (true)
{
if (IsStopped())
return false;
uint diff = GetTickCount() - startWait;
if (diff > 30 * 1000)
{
Print("The waiting limit exceeded!");
return false;
}
if ( IsTradeAllowed() )
{
RefreshRates();
return true;
}
Sleep(TRADE_RETRY_WAIT);
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsOutOfSession()
{
int dayOfWeek = DayOfWeek();
int periodStart = int(Time(0) % 86400);
int periodLength = PeriodSeconds(_Period);
int periodFix = periodStart + (sessionCloseAtSessionClose ? periodLength : 0);
int friBarFix = periodStart + (sessionCloseAtFridayClose || sessionCloseAtSessionClose ? periodLength : 0);
return dayOfWeek == 0 && sessionIgnoreSunday ? true
: dayOfWeek == 0 ? periodStart < sessionSundayOpen || periodFix > sessionSundayClose
: dayOfWeek < 5 ? periodStart < sessionMondayThursdayOpen || periodFix > sessionMondayThursdayClose
: periodStart < sessionFridayOpen || friBarFix > sessionFridayClose;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsForceSessionClose()
{
if (!sessionCloseAtFridayClose && !sessionCloseAtSessionClose)
return false;
int dayOfWeek = DayOfWeek();
int periodEnd = int(Time(0) % 86400) + PeriodSeconds(_Period);
return dayOfWeek == 0 && sessionCloseAtSessionClose ? periodEnd > sessionSundayClose
: dayOfWeek < 5 && sessionCloseAtSessionClose ? periodEnd > sessionMondayThursdayClose
: dayOfWeek == 5 ? periodEnd > sessionFridayClose : false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ENUM_INIT_RETCODE ValidateInit()
{
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
/*STRATEGY MARKET ICMarketsSC-Demo04; EURUSD; M15 */
/*STRATEGY CODE {"properties":{"entryLots":0.47,"tradeDirectionMode":1,"oppositeEntrySignal":1,"stopLoss":5,"takeProfit":100,"useStopLoss":true,"useTakeProfit":false,"isTrailingStop":true},"openFilters":[{"name":"Bollinger Bands","listIndexes":[4,3,0,0,0],"numValues":[5,2.92,0,0,0,0]}],"closeFilters":[{"name":"Moving Averages Crossover","listIndexes":[0,3,0,0,0],"numValues":[14,31,0,0,0,0]}]} */
void CloseAllOrders() {
int total = OrdersTotal();
if (total == 0) return; // No hay órdenes abiertas, salir
for (int i = total - 1; i >= 0; i--) { // iterar desde el final hacia el inicio
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if (OrderType() == OP_BUY || OrderType() == OP_SELL) {
bool close_success = OrderClose(OrderTicket(), OrderLots(), Bid, 0, clrRed); // Cerrar la orden y almacenar el valor de retorno en una variable
if(!close_success) // Si la orden no se ha cerrado correctamente
{
Print("Error al cerrar la orden: ", GetLastError()); // Imprimir el código de error
}
}
}
}
}
void CheckEquity() {
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double max_loss = (MONTO * Maxima_Perdida_Diaria / 100);
if (equity < max_loss) {
CloseAllOrders();
int count = 0;
while (OrdersTotal() > 0 && count < 60) { // revisar durante 60 segundos
Sleep(1000); // esperar 1 segundo antes de volver a revisar
count++;
}
}
}
Editor is loading...