0% found this document useful (0 votes)
265 views8 pages

Final Draft - mq5

The document is a MetaTrader 5 Expert Advisor (EA) script designed for automated trading based on Python bot logic. It includes input parameters for trading symbols, timeframes, indicators, and risk management settings, and implements trading signals based on technical indicators like EMA and RSI. The EA initializes necessary components, checks for existing positions, and executes trades based on calculated signals and risk management strategies.

Uploaded by

muhapikarim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
265 views8 pages

Final Draft - mq5

The document is a MetaTrader 5 Expert Advisor (EA) script designed for automated trading based on Python bot logic. It includes input parameters for trading symbols, timeframes, indicators, and risk management settings, and implements trading signals based on technical indicators like EMA and RSI. The EA initializes necessary components, checks for existing positions, and executes trades based on calculated signals and risk management strategies.

Uploaded by

muhapikarim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 8

//+------------------------------------------------------------------+

//| TranslatedPythonBotEA.mq5 |
//| Based on Python Bot Logic Mentor |
//| kareem junior |
//+------------------------------------------------------------------+
#property copyright "Your Name Here"
#property link "Your Link Here"
#property version "1.00"
#property strict

// Include for CTrade class, makes trading simpler


#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh> // For SymbolInfo class
#include <Trade\AccountInfo.mqh> // For AccountInfo class

// --- Input Parameters (Mirrors Python Configuration) ---


input group "Symbol & Timeframe"
input string InpSymbolToTrade = "Volatility 75 Index"; //
IMPORTANT: EA should usually run on the chart of this symbol
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_M1; //
Timeframe for indicator calculations

input group "Indicator Parameters"


input int InpATRPeriod = 14;
input int InpBBandsPeriod = 20;
input double InpBBandsStdDev = 2.0;
input int InpRSIPeriod = 14;
input int InpEMAFastPeriod = 12;
input int InpEMASlowPeriod = 50;

input group "Risk Management"


input double InpRiskPerTradePercent = 1.0; // e.g., 1.0 for 1%
input double InpATR_SL_Multiplier = 1.5;
input double InpATR_TP_Multiplier = 3.0;
input int InpDefaultSLPips = 100; // Fallback SL if ATR is
zero
input int InpDefaultTPPips = 200; // Fallback TP if ATR is
zero
input ulong InpBotMagicNumber = 23052025; // Unique Magic Number
for this EA's trades
input int InpSlippagePips = 20; // Max allowed slippage in
points

// --- Global Variables ---


CTrade trade; // Trading object
CSymbolInfo symbol; // Symbol information object
CAccountInfo account; // Account information object
string G_CurrentSymbol; // Stores the symbol the EA is running on

// Indicator Handles
int h_ATR;
int h_BB;
int h_RSI;
int h_EMAFast;
int h_EMASlow;

// Arrays to store indicator and price data


double atr_buffer[];
double bb_main_buffer[]; // Middle band
double bb_upper_buffer[]; // Upper band
double bb_lower_buffer[]; // Lower band
double rsi_buffer[];
double ema_fast_buffer[];
double ema_slow_buffer[];
MqlRates rates[]; // For OHLC, Time, Volume

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
G_CurrentSymbol = _Symbol; // Get the symbol of the chart the EA is attached to
Print("OnInit: EA Starting on symbol ", G_CurrentSymbol, " timeframe ",
EnumToString(InpTimeframe));

// Initialize SymbolInfo and AccountInfo objects


if(!symbol.Name(G_CurrentSymbol))
{
Print("Error setting symbol for CSymbolInfo: ", GetLastError());
return(INIT_FAILED);
}
if(!account.Refresh()) // Refresh account data
{
Print("Error refreshing account info: ", GetLastError());
// Can still proceed, but lot size calculation might use stale equity if it
fails repeatedly
}

// Initialize CTrade object


trade.SetExpertMagicNumber(InpBotMagicNumber);
trade.SetDeviationInPoints(InpSlippagePips); // Max allowed price deviation
(slippage)
trade.SetTypeFillingBySymbol(G_CurrentSymbol); // Auto-detect filling mode, or
set specific like ORDER_FILLING_IOC

// --- Initialize Indicator Handles ---


// ATR
h_ATR = iATR(G_CurrentSymbol, InpTimeframe, InpATRPeriod);
if(h_ATR == INVALID_HANDLE)
{
Print("Error creating ATR indicator handle: ", GetLastError());
return(INIT_FAILED);
}

// Bollinger Bands
h_BB = iBands(G_CurrentSymbol, InpTimeframe, InpBBandsPeriod, 0,
InpBBandsStdDev, PRICE_CLOSE);
if(h_BB == INVALID_HANDLE)
{
Print("Error creating Bollinger Bands indicator handle: ", GetLastError());
return(INIT_FAILED);
}

// RSI
h_RSI = iRSI(G_CurrentSymbol, InpTimeframe, InpRSIPeriod, PRICE_CLOSE);
if(h_RSI == INVALID_HANDLE)
{
Print("Error creating RSI indicator handle: ", GetLastError());
return(INIT_FAILED);
}

// EMA Fast
h_EMAFast = iMA(G_CurrentSymbol, InpTimeframe, InpEMAFastPeriod, 0, MODE_EMA,
PRICE_CLOSE);
if(h_EMAFast == INVALID_HANDLE)
{
Print("Error creating Fast EMA indicator handle: ", GetLastError());
return(INIT_FAILED);
}

// EMA Slow
h_EMASlow = iMA(G_CurrentSymbol, InpTimeframe, InpEMASlowPeriod, 0, MODE_EMA,
PRICE_CLOSE);
if(h_EMASlow == INVALID_HANDLE)
{
Print("Error creating Slow EMA indicator handle: ", GetLastError());
return(INIT_FAILED);
}

// Set arrays as series (latest data at index 0)


ArraySetAsSeries(rates, true);
ArraySetAsSeries(atr_buffer, true);
ArraySetAsSeries(bb_main_buffer, true);
ArraySetAsSeries(bb_upper_buffer, true);
ArraySetAsSeries(bb_lower_buffer, true);
ArraySetAsSeries(rsi_buffer, true);
ArraySetAsSeries(ema_fast_buffer, true);
ArraySetAsSeries(ema_slow_buffer, true);

Print("OnInit: Initialization successful.");


return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("OnDeinit: EA Stopping. Reason code: ", reason);
// Release indicator handles
IndicatorRelease(h_ATR);
IndicatorRelease(h_BB);
IndicatorRelease(h_RSI);
IndicatorRelease(h_EMAFast);
IndicatorRelease(h_EMASlow);
}

//+------------------------------------------------------------------+
//| Expert tick function (called on every new price tick) |
//+------------------------------------------------------------------+
void OnTick()
{
// --- 0. Allow trading? Check terminal & EA settings ---
if(!MQLInfoInteger(MQL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_SERVER))
{
// Comment("Trading is not allowed for this account or server.");
return;
}
if(IsStopped()) // Check if EA was stopped from Experts tab
{
return;
}

// --- 1. Get Latest Data (OHLC and Indicators) ---


if(CopyRates(G_CurrentSymbol, InpTimeframe, 0, 3, rates) < 3) // Need at least
2-3 bars for prev/current
{
Print("Error copying rates: ", GetLastError());
return;
}

// Copy indicator buffers (typically need values for current [0] and previous
[1] bar)
// For signals, it's often safer to use data from the most recently COMPLETED
bar (index 1)
// Index 0 is the current, developing bar.
int bars_to_copy = 3; // Get a few bars for safety
if(CopyBuffer(h_ATR, 0, 0, bars_to_copy, atr_buffer) < bars_to_copy) return;
if(CopyBuffer(h_BB, 0, 0, bars_to_copy, bb_main_buffer) < bars_to_copy)
return; // Main Line
if(CopyBuffer(h_BB, 1, 0, bars_to_copy, bb_upper_buffer) < bars_to_copy) return;
// Upper Band
if(CopyBuffer(h_BB, 2, 0, bars_to_copy, bb_lower_buffer) < bars_to_copy) return;
// Lower Band
if(CopyBuffer(h_RSI, 0, 0, bars_to_copy, rsi_buffer) < bars_to_copy) return;
if(CopyBuffer(h_EMAFast, 0, 0, bars_to_copy, ema_fast_buffer) < bars_to_copy)
return;
if(CopyBuffer(h_EMASlow, 0, 0, bars_to_copy, ema_slow_buffer) < bars_to_copy)
return;

// --- 2. Check for Existing Position by this Bot ---


if(CheckExistingPosition())
{
// Print("An active trade with magic number ", InpBotMagicNumber, " already
exists for ", G_CurrentSymbol);
return; // Don't open new trades if one is already open by this EA
}

// --- 3. Get Trading Signal (Translate Python's get_trading_signal logic here)


---
// Example: Use values from index 1 (most recent fully closed bar) for signals
// Use values from index 0 (current bar) for entry price points
double current_close = rates[0].close; // Or rates[1].close for confirmed bar
close
double prev_close = rates[1].close;

double ema_fast_current = ema_fast_buffer[0]; // Current bar, might repaint


double ema_fast_prev = ema_fast_buffer[1]; // Previous completed bar
double ema_slow_current = ema_slow_buffer[0];
double ema_slow_prev = ema_slow_buffer[1];
double rsi_current = rsi_buffer[0]; // Or rsi_buffer[1]

string signal = "HOLD"; // "BUY", "SELL", "HOLD"

// Implement EMA Crossover with RSI filter from Python script:


// Buy signal: prev Fast EMA <= prev Slow EMA AND current Fast EMA > current
Slow EMA AND current RSI < 70
if (ema_fast_prev <= ema_slow_prev && ema_fast_current > ema_slow_current &&
rsi_current < 70.0)
{
signal = "BUY";
}
// Sell signal: prev Fast EMA >= prev Slow EMA AND current Fast EMA < current
Slow EMA AND current RSI > 30
else if (ema_fast_prev >= ema_slow_prev && ema_fast_current < ema_slow_current
&& rsi_current > 30.0)
{
signal = "SELL";
}

// Print("Signal: ", signal, " FastEMA_prev: ", ema_fast_prev, " SlowEMA_prev:


", ema_slow_prev, " RSI: ", rsi_current);

// --- 4. If No Existing Position and Valid Signal, then Trade ---


if(signal != "HOLD")
{
double current_atr = atr_buffer[0]; // Or atr_buffer[1] for stability
if(current_atr == 0 || NormalizedDouble(current_atr, _Digits) == 0) // Check
for valid ATR
{
Print("ATR is zero or invalid. Cannot calculate SL/TP dynamically.
Skipping trade.");
// Optionally use default SL/TP pips here, but be cautious
return;
}

// a. Calculate SL and TP distances in points (not pips, MQL5 points)


double point_value = symbol.Point(); // _Point can also be used
double sl_distance_points = (current_atr * InpATR_SL_Multiplier);
double tp_distance_points = (current_atr * InpATR_TP_Multiplier);

// If ATR is too small, use default pips converted to points


if(sl_distance_points / point_value < 1) sl_distance_points =
InpDefaultSLPips * point_value * pow(10, _Digits - symbol.Digits()); // Adjust for
fractional pips
if(tp_distance_points / point_value < 1) tp_distance_points =
InpDefaultTPPips * point_value * pow(10, _Digits - symbol.Digits());

// b. Calculate Lot Size


double lot_size = CalculateLotSize(sl_distance_points);
if(lot_size < symbol.LotsMin())
{
Print("Calculated lot size ", lot_size, " is less than minimum allowed ",
symbol.LotsMin(), ". Adjusting to min or skipping.");
// lot_size = symbol.LotsMin(); // Option: force min lot
// return; // Option: skip trade
if(symbol.LotsMin() > 0) lot_size = symbol.LotsMin(); // Only if min lot
is positive
else { Print("Min lot size is zero or negative, cannot trade."); return; }
}
// c. Define SL and TP price levels
double entry_price_ask = symbol.Ask(); // For BUY
double entry_price_bid = symbol.Bid(); // For SELL
double sl_price = 0.0;
double tp_price = 0.0;

if(signal == "BUY")
{
sl_price = entry_price_ask - sl_distance_points;
tp_price = entry_price_ask + tp_distance_points;
Print("Attempting BUY: Lot=", lot_size, " SL=", sl_price, " TP=",
tp_price, " EntryAsk=", entry_price_ask);
if(!trade.Buy(lot_size, G_CurrentSymbol, entry_price_ask, sl_price,
tp_price, "PythonLogicEA BUY"))
{
Print("BUY order failed: ", trade.ResultRetcode(), " - ",
trade.ResultComment());
}
else
{
Print("BUY order placed successfully. Ticket: ", trade.ResultOrder());
}
}
else if(signal == "SELL")
{
sl_price = entry_price_bid + sl_distance_points;
tp_price = entry_price_bid - tp_distance_points;
Print("Attempting SELL: Lot=", lot_size, " SL=", sl_price, " TP=",
tp_price, " EntryBid=", entry_price_bid);
if(!trade.Sell(lot_size, G_CurrentSymbol, entry_price_bid, sl_price,
tp_price, "PythonLogicEA SELL"))
{
Print("SELL order failed: ", trade.ResultRetcode(), " - ",
trade.ResultComment());
}
else
{
Print("SELL order placed successfully. Ticket: ", trade.ResultOrder());
}
}
}
}

//+------------------------------------------------------------------+
//| Helper Function: Calculate Lot Size based on Risk % and SL |
//+------------------------------------------------------------------+
double CalculateLotSize(double sl_distance_points) // sl_distance_points is the
distance from entry to SL in PRICE units
{
account.Refresh(); // Get latest account info
double acc_equity = account.Equity();
double risk_amount = acc_equity * (InpRiskPerTradePercent / 100.0);

if(sl_distance_points <= 0)
{
Print("SL distance is zero or negative (", sl_distance_points, "). Cannot
calculate lot size. Using min lot.");
return(symbol.LotsMin());
}
// Value of 1 lot SL
// double tick_value = symbol.TickValue(); // Value of a 1-point move for 1 lot
in deposit currency
// double sl_value_per_lot = sl_distance_points / symbol.Point() *
tick_value; // This is more complex with varying contract specs

// Simplified: Value of 1 point move for 1 lot in deposit currency


// For Forex, TickValue is often per tick, and Point is the size of the tick.
// For Indices, it can be different. We need value per point for 1 lot.
// SymbolInfoDouble(G_CurrentSymbol, SYMBOL_TRADE_TICK_VALUE_LOSS) or
SYMBOL_TRADE_TICK_VALUE_PROFIT
// A more robust way:
double one_lot_value_per_point = 0;
MqlTick latest_tick;
SymbolInfoTick(G_CurrentSymbol, latest_tick);

// Calculate profit/loss for a 1 point move with 1 lot


// This is tricky because SYMBOL_TRADE_TICK_VALUE is value of
SYMBOL_TRADE_TICK_SIZE move.
// If SYMBOL_TRADE_TICK_SIZE is not equal to SYMBOL_POINT, adjustment is needed.
// Let's assume SYMBOL_TRADE_TICK_VALUE is for a move of SYMBOL_TRADE_TICK_SIZE.
// Value per point = SYMBOL_TRADE_TICK_VALUE / (SYMBOL_TRADE_TICK_SIZE /
SYMBOL_POINT)

double tick_value = symbol.TickValue(); // Value of a SYMBOL_TRADE_TICK_SIZE


move for 1.0 lot
double tick_size = symbol.TickSize();
double point = symbol.Point();

if (tick_size == 0) return symbol.LotsMin(); // Avoid division by zero

double value_per_point_one_lot = tick_value / (tick_size / point) ;


double sl_value_per_lot = (sl_distance_points / point) *
value_per_point_one_lot;

if(sl_value_per_lot <= 0)
{
Print("SL value per lot is zero or negative (", sl_value_per_lot, "). Cannot
calculate lot size. Using min lot.");
return(symbol.LotsMin());
}

double desired_lot_size = risk_amount / sl_value_per_lot;

// Normalize lot size according to symbol's contract specification


double min_lot = symbol.LotsMin();
double max_lot = symbol.LotsMax();
double step_lot = symbol.LotsStep();

desired_lot_size = MathMax(min_lot, desired_lot_size); // Not less than


min_lot
desired_lot_size = MathMin(max_lot, desired_lot_size); // Not more than
max_lot
desired_lot_size = MathFloor(desired_lot_size / step_lot) * step_lot; // Adhere
to volume step

// Ensure it's rounded to the correct number of decimal places for lot size
int lot_digits = 0;
string step_str = DoubleToString(step_lot, 8); // Convert step to string to find
decimal places
int dot_pos = StringFind(step_str, ".");
if(dot_pos >= 0) lot_digits = StringLen(step_str) - dot_pos - 1;

desired_lot_size = NormalizeDouble(desired_lot_size, lot_digits);

Print("LotCalc: Equity=", acc_equity, " RiskAmt=", risk_amount, " SL_Dist_Pts=",


sl_distance_points, " SL_Val_Per_Lot=", sl_value_per_lot, " CalcLot=",
desired_lot_size);
return(desired_lot_size);
}

//+------------------------------------------------------------------+
//| Helper Function: Check if a position by this EA already exists |
//+------------------------------------------------------------------+
bool CheckExistingPosition()
{
for(int i = PositionsTotal() - 1; i >= 0; i--) // Loop through all open
positions
{
ulong pos_ticket = PositionGetTicket(i); // Get ticket of position at index i
if(PositionSelectByTicket(pos_ticket)) // Select the position to access its
properties
{
// Check if the position is for the current symbol and has the EA's magic
number
if(PositionGetString(POSITION_SYMBOL) == G_CurrentSymbol &&
PositionGetInteger(POSITION_MAGIC) == InpBotMagicNumber)
{
return(true); // Position found
}
}
}
return(false); // No matching position found
}
//+------------------------------------------------------------------+

You might also like