mql5/Experts/Advisors/otc_escape.mq5

330 lines
11 KiB
MQL5
Raw Permalink Normal View History

2025-08-05 01:57:33 -04:00
//+------------------------------------------------------------------+
//| OTC Escape EA |
//| Optimized for OTC Markets |
//| Based on escape.mq5 template |
//+------------------------------------------------------------------+
#property version "1.000"
#property strict
//--- Include files
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
//--- Global Objects
CPositionInfo m_position; // trade position object
CTrade m_trade; // trading object
CSymbolInfo m_symbol; // symbol info object
CAccountInfo m_account; // account info wrapper
CDealInfo m_deal; // deals object
COrderInfo m_order; // pending orders object
//--- Input Parameters (Optimized for OTC Markets)
input ushort InpTakeProfit_l = 40; // TakeProfit for long positions (points)
input ushort InpTakeProfit_s = 40; // TakeProfit for short positions (points)
input ushort InpStopLoss_l = 30; // StopLoss for long positions (points)
input ushort InpStopLoss_s = 30; // StopLoss for short positions (points)
input string InpName_Expert = "OTC_Escape"; // Expert Name
input ulong InpSlippage = 3; // Slippage (points)
input bool UseSound = false; // Enable sounds
input string NameFileSound = "Alert.wav"; // Sound file
input double InpLots = 0.1; // Lot size
input int InpMAPeriod1 = 5; // Fast MA Period
input int InpMAPeriod2 = 10; // Slow MA Period
input ENUM_MA_METHOD InpMAMethod = MODE_SMA; // MA Method
input ENUM_APPLIED_PRICE InpMAPrice = PRICE_CLOSE; // MA Price
input int InpMaxSpread = 30; // Maximum allowed spread (points)
input bool InpUseTimeFilter = true; // Use time filter
input int InpStartHour = 1; // Start trading hour (broker time)
input int InpEndHour = 22; // End trading hour (broker time)
//--- Global Variables
ulong m_magic = 987569; // Magic number
int m_digits_adjust = 1; // Digits adjustment
bool m_is_otc = true; // OTC market flag
//--- Indicator Handles
int handle_ma_fast; // Handle for fast MA
int handle_ma_slow; // Handle for slow MA
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Initialize symbol and trading objects
m_symbol.Name(Symbol());
m_trade.SetExpertMagicNumber(m_magic);
m_trade.SetDeviationInPoints(InpSlippage);
m_trade.SetTypeFilling(ORDER_FILLING_FOK);
//--- Check if symbol is valid for OTC trading
if(!IsOTCSymbol())
{
Print("Warning: This EA is optimized for OTC symbols. Current symbol: ", Symbol());
m_is_otc = false;
}
//--- Initialize indicator handles
handle_ma_fast = iMA(Symbol(), Period(), InpMAPeriod1, 0, InpMAMethod, InpMAPrice);
handle_ma_slow = iMA(Symbol(), Period(), InpMAPeriod2, 0, InpMAMethod, InpMAPrice);
//--- Check if indicator handles are valid
if(handle_ma_fast == INVALID_HANDLE || handle_ma_slow == INVALID_HANDLE)
{
Print("Error creating indicator handles");
return(INIT_FAILED);
}
//--- Adjust for 3/5 digit brokers
m_digits_adjust = (m_symbol.Digits() == 3 || m_symbol.Digits() == 5) ? 10 : 1;
//--- Check if we have enough bars
if(Bars(Symbol(), Period()) < 100)
{
Print("Not enough bars");
return(INIT_FAILED);
}
//--- All initialization successful
Print("OTC Escape EA initialized successfully");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Release indicator handles
if(handle_ma_fast != INVALID_HANDLE)
IndicatorRelease(handle_ma_fast);
if(handle_ma_slow != INVALID_HANDLE)
IndicatorRelease(handle_ma_slow);
Comment("");
Print("EA deinitialized");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Check for new bar
static datetime last_bar = 0;
datetime current_bar = (datetime)SeriesInfoInteger(Symbol(), Period(), SERIES_LASTBAR_DATE);
if(last_bar == current_bar)
return;
last_bar = current_bar;
//--- Check if we can trade
if(!CanTrade())
return;
//--- Check for open positions
if(PositionsTotal() > 0)
{
CheckForClose();
return;
}
//--- Check for new trading signals
CheckForOpen();
}
//+------------------------------------------------------------------+
//| Check if we can trade |
//+------------------------------------------------------------------+
bool CanTrade()
{
//--- Check if market is open
if(m_is_otc)
{
// OTC markets might have different trading hours
if(InpUseTimeFilter)
{
datetime time = TimeCurrent();
MqlDateTime tm;
TimeToStruct(time, tm);
if(tm.hour < InpStartHour || tm.hour >= InpEndHour)
return false;
}
}
//--- Check spread
double spread = m_symbol.Ask() - m_symbol.Bid();
if(spread > m_symbol.Point() * InpMaxSpread)
{
Print("Spread too high: ", spread / m_symbol.Point(), " points");
return false;
}
//--- Check if we have enough money
if(m_account.FreeMargin() < (1000 * InpLots))
{
Print("Not enough free margin. Free Margin = ", m_account.FreeMargin());
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Check for open positions |
//+------------------------------------------------------------------+
void CheckForOpen()
{
//--- Get indicator values
double ma_fast[2], ma_slow[2];
if(CopyBuffer(handle_ma_fast, 0, 0, 2, ma_fast) <= 0 ||
CopyBuffer(handle_ma_slow, 0, 0, 2, ma_slow) <= 0)
{
Print("Error copying indicator buffers");
return;
}
//--- Check for buy signal (fast MA crosses above slow MA)
if(ma_fast[1] <= ma_slow[1] && ma_fast[0] > ma_slow[0])
{
OpenBuy();
return;
}
//--- Check for sell signal (fast MA crosses below slow MA)
if(ma_fast[1] >= ma_slow[1] && ma_fast[0] < ma_slow[0])
{
OpenSell();
return;
}
}
//+------------------------------------------------------------------+
//| Check for close positions |
//+------------------------------------------------------------------+
void CheckForClose()
{
// Check if we have an open position on the current symbol
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol() == Symbol() && m_position.Magic() == m_magic)
{
// Check if we need to close the position based on some condition
// This is a simple example - you might want to add more sophisticated logic
if(m_position.PositionType() == POSITION_TYPE_BUY)
{
if(m_position.Profit() > 0 &&
m_symbol.Bid() >= m_position.PriceOpen() + InpTakeProfit_l * m_symbol.Point())
{
m_trade.PositionClose(m_position.Ticket());
}
else if(m_symbol.Bid() <= m_position.PriceOpen() - InpStopLoss_l * m_symbol.Point())
{
m_trade.PositionClose(m_position.Ticket());
}
}
else // POSITION_TYPE_SELL
{
if(m_position.Profit() > 0 &&
m_symbol.Ask() <= m_position.PriceOpen() - InpTakeProfit_s * m_symbol.Point())
{
m_trade.PositionClose(m_position.Ticket());
}
else if(m_symbol.Ask() >= m_position.PriceOpen() + InpStopLoss_s * m_symbol.Point())
{
m_trade.PositionClose(m_position.Ticket());
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| Open Buy position |
//+------------------------------------------------------------------+
void OpenBuy()
{
if(!RefreshRates())
{
Print("Error refreshing rates");
return;
}
double sl = (InpStopLoss_l > 0) ? m_symbol.Ask() - InpStopLoss_l * m_symbol.Point() : 0.0;
double tp = (InpTakeProfit_l > 0) ? m_symbol.Ask() + InpTakeProfit_l * m_symbol.Point() : 0.0;
m_trade.Buy(InpLots, m_symbol.Name(), m_symbol.Ask(), sl, tp, "OTC_Escape_Buy");
if(UseSound)
PlaySound(NameFileSound);
}
//+------------------------------------------------------------------+
//| Open Sell position |
//+------------------------------------------------------------------+
void OpenSell()
{
if(!RefreshRates())
{
Print("Error refreshing rates");
return;
}
double sl = (InpStopLoss_s > 0) ? m_symbol.Bid() + InpStopLoss_s * m_symbol.Point() : 0.0;
double tp = (InpTakeProfit_s > 0) ? m_symbol.Bid() - InpTakeProfit_s * m_symbol.Point() : 0.0;
m_trade.Sell(InpLots, m_symbol.Name(), m_symbol.Bid(), sl, tp, "OTC_Escape_Sell");
if(UseSound)
PlaySound(NameFileSound);
}
//+------------------------------------------------------------------+
//| Check if the symbol is an OTC symbol |
//+------------------------------------------------------------------+
bool IsOTCSymbol()
{
// Add your OTC symbol detection logic here
// This is a simple example - you might want to customize it based on your broker's OTC symbols
string symbol = Symbol();
StringToLower(symbol);
// Common OTC symbols might include 'otc' in the name or have specific prefixes/suffixes
if(StringFind(symbol, "otc") >= 0 ||
StringFind(symbol, "cfd") >= 0 ||
StringFind(symbol, "_o") >= 0)
{
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Refresh rates and check for errors |
//+------------------------------------------------------------------+
bool RefreshRates()
{
if(!m_symbol.RefreshRates())
{
Print("Error refreshing symbol data");
return false;
}
if(m_symbol.Ask() == 0 || m_symbol.Bid() == 0)
{
Print("Invalid price data");
return false;
}
return true;
}
//+------------------------------------------------------------------+