277 lines
11 KiB
MQL5
277 lines
11 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| OTC Escape EA (Learning) V2 |
|
||
|
|
//| Optimized for OTC Markets |
|
||
|
|
//| With Machine Learning |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property version "2.00"
|
||
|
|
#property strict
|
||
|
|
|
||
|
|
//--- Include files
|
||
|
|
#include <Trade\PositionInfo.mqh>
|
||
|
|
#include <Trade\Trade.mqh>
|
||
|
|
#include <Trade\SymbolInfo.mqh>
|
||
|
|
#include <Trade\AccountInfo.mqh>
|
||
|
|
#include <Arrays\ArrayObj.mqh>
|
||
|
|
#include <OTCTypes.mqh>
|
||
|
|
#include <OTCLearningEngine.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
|
||
|
|
CLearningEngine *learning_engine = NULL; // learning engine object
|
||
|
|
|
||
|
|
//--- Indicator Handles
|
||
|
|
int handle_ma_fast, handle_ma_slow, handle_rsi, handle_adx, handle_atr;
|
||
|
|
|
||
|
|
//--- Indicator Buffers
|
||
|
|
double ma_fast_buffer[], ma_slow_buffer[], rsi_buffer[], adx_buffer[], atr_buffer[];
|
||
|
|
|
||
|
|
//--- Input Parameters
|
||
|
|
input ulong InpMagicNumber = 12345; // Magic Number
|
||
|
|
input ushort InpTakeProfit = 40; // TakeProfit for positions (pips)
|
||
|
|
input ushort InpStopLoss = 30; // StopLoss for positions (pips)
|
||
|
|
input bool InpUseStopLoss = true; // Use stop loss
|
||
|
|
input bool InpUseTakeProfit= true; // Use take profit
|
||
|
|
input string InpName_Expert = "OTC_Escape_Learning_V2"; // Expert Name
|
||
|
|
input ulong InpSlippage = 3; // Slippage (points)
|
||
|
|
input double InpLots = 0.02; // 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 group "=== Advanced Strategy Settings ==="
|
||
|
|
input int InpRSI_Period = 14; // RSI Period
|
||
|
|
input int InpADX_Period = 14; // ADX Period
|
||
|
|
input int InpATR_Period = 14; // ATR Period
|
||
|
|
input double InpADX_Threshold = 25.0; // ADX trend strength threshold
|
||
|
|
input double InpATR_SL_Multiplier = 2.0; // ATR multiplier for Stop Loss
|
||
|
|
input double InpATR_TP_Multiplier = 1.5; // Reward:Risk Ratio for Take Profit
|
||
|
|
|
||
|
|
input group "=== Order Settings ==="
|
||
|
|
input int InpMaxOpenTrades = 5; // Maximum number of open trades
|
||
|
|
|
||
|
|
input group "=== Learning Engine Settings ==="
|
||
|
|
input bool InpUseLearning = true; // Enable learning engine
|
||
|
|
input bool InpUseAdaptiveLogic = true; // Enable adaptive SL/TP logic
|
||
|
|
input int InpMinTradesForAnalysis = 50; // Min trades per regime to adapt
|
||
|
|
input double InpVolatilityThreshold = 0.001; // Volatility threshold for regime change
|
||
|
|
input double InpTrendThreshold = 20.0; // Trend strength threshold for regime change
|
||
|
|
|
||
|
|
//--- Global Variables for Adaptive Logic
|
||
|
|
double g_adaptive_sl_pips = 0;
|
||
|
|
double g_adaptive_tp_pips = 0;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Expert initialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit()
|
||
|
|
{
|
||
|
|
m_symbol.Name(Symbol());
|
||
|
|
m_trade.SetExpertMagicNumber(InpMagicNumber);
|
||
|
|
m_trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||
|
|
|
||
|
|
handle_ma_fast = iMA(Symbol(), Period(), InpMAPeriod1, 0, InpMAMethod, InpMAPrice);
|
||
|
|
handle_ma_slow = iMA(Symbol(), Period(), InpMAPeriod2, 0, InpMAMethod, InpMAPrice);
|
||
|
|
handle_rsi = iRSI(Symbol(), Period(), InpRSI_Period, InpMAPrice);
|
||
|
|
handle_adx = iADX(Symbol(), Period(), InpADX_Period);
|
||
|
|
handle_atr = iATR(Symbol(), Period(), InpATR_Period);
|
||
|
|
|
||
|
|
if(handle_ma_fast == INVALID_HANDLE || handle_ma_slow == INVALID_HANDLE || handle_rsi == INVALID_HANDLE || handle_adx == INVALID_HANDLE || handle_atr == INVALID_HANDLE)
|
||
|
|
{
|
||
|
|
Print("Error creating indicators");
|
||
|
|
return(INIT_FAILED);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
if(InpUseLearning)
|
||
|
|
{
|
||
|
|
learning_engine = new CLearningEngine(InpVolatilityThreshold, InpTrendThreshold);
|
||
|
|
if(CheckPointer(learning_engine) == POINTER_INVALID)
|
||
|
|
{
|
||
|
|
learning_engine = new CLearningEngine();
|
||
|
|
if(CheckPointer(learning_engine) == POINTER_INVALID)
|
||
|
|
{
|
||
|
|
ExpertRemove();
|
||
|
|
return(INIT_FAILED);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
learning_engine->Init(Symbol(), Period());
|
||
|
|
learning_engine->SetMinTradesForAnalysis(InpMinTradesForAnalysis);
|
||
|
|
}
|
||
|
|
|
||
|
|
Print("OTC Escape EA V2 initialized successfully");
|
||
|
|
return(INIT_SUCCEEDED);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Expert deinitialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnDeinit(const int reason)
|
||
|
|
{
|
||
|
|
IndicatorRelease(handle_ma_fast);
|
||
|
|
IndicatorRelease(handle_ma_slow);
|
||
|
|
IndicatorRelease(handle_rsi);
|
||
|
|
IndicatorRelease(handle_adx);
|
||
|
|
IndicatorRelease(handle_atr);
|
||
|
|
|
||
|
|
if(CheckPointer(learning_engine) == POINTER_DYNAMIC)
|
||
|
|
{
|
||
|
|
delete learning_engine;
|
||
|
|
}
|
||
|
|
Print("OTC Escape EA V2 deinitialized");
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Expert tick function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnTick()
|
||
|
|
{
|
||
|
|
m_symbol.RefreshRates();
|
||
|
|
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;
|
||
|
|
|
||
|
|
//--- Copy indicator data
|
||
|
|
ArraySetAsSeries(ma_fast_buffer, true);
|
||
|
|
ArraySetAsSeries(ma_slow_buffer, true);
|
||
|
|
ArraySetAsSeries(rsi_buffer, true);
|
||
|
|
ArraySetAsSeries(adx_buffer, true);
|
||
|
|
ArraySetAsSeries(atr_buffer, true);
|
||
|
|
|
||
|
|
if(CopyBuffer(handle_ma_fast, 0, 0, 2, ma_fast_buffer) < 2 ||
|
||
|
|
CopyBuffer(handle_ma_slow, 0, 0, 2, ma_slow_buffer) < 2 ||
|
||
|
|
CopyBuffer(handle_rsi, 0, 0, 2, rsi_buffer) < 2 ||
|
||
|
|
CopyBuffer(handle_adx, 0, 0, 2, adx_buffer) < 2 ||
|
||
|
|
CopyBuffer(handle_atr, 0, 0, 2, atr_buffer) < 2)
|
||
|
|
{
|
||
|
|
Print("Error copying indicator buffers in OnTick");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(InpUseAdaptiveLogic)
|
||
|
|
{
|
||
|
|
AdaptParameters();
|
||
|
|
}
|
||
|
|
|
||
|
|
CheckForOpen();
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Check for new trade signals |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void CheckForOpen()
|
||
|
|
{
|
||
|
|
if(m_position.Select(Symbol()))
|
||
|
|
{
|
||
|
|
return; // Position already exists
|
||
|
|
}
|
||
|
|
|
||
|
|
bool buy_signal = ma_fast_buffer[1] > ma_slow_buffer[1] && adx_buffer[1] > InpADX_Threshold;
|
||
|
|
bool sell_signal = ma_fast_buffer[1] < ma_slow_buffer[1] && adx_buffer[1] > InpADX_Threshold;
|
||
|
|
|
||
|
|
// Determine SL and TP in pips
|
||
|
|
double sl_pips, tp_pips;
|
||
|
|
if(InpUseAdaptiveLogic && g_adaptive_sl_pips > 0)
|
||
|
|
{
|
||
|
|
sl_pips = g_adaptive_sl_pips;
|
||
|
|
tp_pips = g_adaptive_tp_pips;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
double atr_value = atr_buffer[1];
|
||
|
|
if(atr_value <= 0) return; // Cannot set SL/TP without ATR
|
||
|
|
sl_pips = atr_value / _Point * InpATR_SL_Multiplier;
|
||
|
|
tp_pips = sl_pips * InpATR_TP_Multiplier;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(buy_signal)
|
||
|
|
{
|
||
|
|
OpenTrade(ORDER_TYPE_BUY, InpLots, sl_pips, tp_pips);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(sell_signal)
|
||
|
|
{
|
||
|
|
OpenTrade(ORDER_TYPE_SELL, InpLots, sl_pips, tp_pips);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Open a new trade |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OpenTrade(ENUM_ORDER_TYPE OrderType, double LotSize, double sl_pips, double tp_pips)
|
||
|
|
{
|
||
|
|
double price = (OrderType == ORDER_TYPE_BUY) ? m_symbol.Ask() : m_symbol.Bid();
|
||
|
|
|
||
|
|
// Calculate SL/TP prices from pips
|
||
|
|
double sl_price = (sl_pips > 0) ? ((OrderType == ORDER_TYPE_BUY) ? price - sl_pips * _Point : price + sl_pips * _Point) : 0;
|
||
|
|
double tp_price = (tp_pips > 0) ? ((OrderType == ORDER_TYPE_BUY) ? price + tp_pips * _Point : price - tp_pips * _Point) : 0;
|
||
|
|
|
||
|
|
//--- High-Precision Diagnostic Log
|
||
|
|
string log_message = StringFormat("Attempting PositionOpen: symbol=%s, type=%s, lot=%.2f, entry=%.5f, sl=%.5f, tp=%.5f",
|
||
|
|
_Symbol, (OrderType == ORDER_TYPE_BUY ? "BUY" : "SELL"), LotSize, price, sl_price, tp_price);
|
||
|
|
Print(log_message);
|
||
|
|
|
||
|
|
// Corrected call using PositionOpen
|
||
|
|
if(!m_trade.PositionOpen(_Symbol, OrderType, LotSize, price, sl_price, tp_price, "EA V2 Trade"))
|
||
|
|
{
|
||
|
|
PrintFormat("PositionOpen failed: %d - %s", m_trade.ResultRetcode(), m_trade.ResultComment());
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Print("Position opened successfully");
|
||
|
|
if(InpUseLearning && CheckPointer(learning_engine) == POINTER_DYNAMIC)
|
||
|
|
{
|
||
|
|
STradeRecord *trade_record = new STradeRecord();
|
||
|
|
if(CheckPointer(trade_record) != POINTER_INVALID)
|
||
|
|
{
|
||
|
|
trade_record->trade_type = OrderType;
|
||
|
|
trade_record->entry_time = TimeCurrent();
|
||
|
|
trade_record->entry_price = m_trade.ResultPrice();
|
||
|
|
trade_record->lot_size = LotSize;
|
||
|
|
trade_record->stop_loss = m_trade.ResultSL();
|
||
|
|
trade_record->take_profit = m_trade.ResultTP();
|
||
|
|
trade_record->spread = (m_symbol.Ask() - m_symbol.Bid()) / _Point;
|
||
|
|
trade_record->volatility = atr_buffer[1];
|
||
|
|
trade_record->trend_strength = adx_buffer[1];
|
||
|
|
trade_record->market_regime = learning_engine->GetCurrentMarketRegime(trade_record->volatility, trade_record->trend_strength);
|
||
|
|
learning_engine->AddTrade(trade_record);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Adapt strategy parameters based on learned data |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void AdaptParameters()
|
||
|
|
{
|
||
|
|
if(CheckPointer(learning_engine) == POINTER_INVALID) return;
|
||
|
|
|
||
|
|
double current_volatility = atr_buffer[1];
|
||
|
|
double current_trend = adx_buffer[1];
|
||
|
|
|
||
|
|
SMarketState market_state;
|
||
|
|
market_state.Reset();
|
||
|
|
market_state.regime = learning_engine->GetCurrentMarketRegime(current_volatility, current_trend);
|
||
|
|
|
||
|
|
if(learning_engine->GetOptimizedParameters(market_state))
|
||
|
|
{
|
||
|
|
if(market_state.optimal_sl > 0 && market_state.optimal_tp > 0)
|
||
|
|
{
|
||
|
|
g_adaptive_tp_pips = market_state.optimal_tp;
|
||
|
|
g_adaptive_sl_pips = market_state.optimal_sl;
|
||
|
|
PrintFormat("AdaptParameters: Parameters updated for regime %s. New TP: %.1f, SL: %.1f",
|
||
|
|
EnumToString(market_state.regime), g_adaptive_tp_pips, g_adaptive_sl_pips);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
g_adaptive_sl_pips = 0;
|
||
|
|
g_adaptive_tp_pips = 0;
|
||
|
|
}
|
||
|
|
}
|