//+------------------------------------------------------------------+
//| Try.mq5 |
//| Best-Performing Version (v1.2) |
//| [Focus on Shorts + SMA20 Filter + Dynamic RR] |
//+------------------------------------------------------------------+
#include <Trade/[Link]>
#include <Trade/[Link]>
//+------------------------------------------------------------------+
//| Input Parameters |
//+------------------------------------------------------------------+
input ulong MagicNumber = 12345; // EA Magic Number
input int ATR_Period = 14; // ATR period for volatility
input bool UseTrailingStop = true; // Enable trailing stop
input int MaxSpread = 15; // Max allowed spread (points)
//--- Set 6: High RR Compensation ---
input int FastMAPeriod = 3; // Fast MA period
input int SlowMAPeriod = 9; // Slow MA period
input double RiskPercent = 0.5; // Base risk per trade
input int ADX_Period = 10; // ADX period
input int MinADX = 14; // Minimum ADX threshold
input double ATR_Multiplier = 0.9; // Reduced ATR multiplier for tighter stops
input int TrailStart = 25; // Trailing stop activation (pips)
input int TrailStep = 10; // Trailing stop step (pips)
// Global variables
int fastMAHandle, slowMAHandle, adxHandle, atrHandle, smaHandle;
CTrade trade;
CAccountInfo account;
double dynamicRiskPercent; // Dynamic risk adjustment variable
int consecutiveLosses = 0; // Track consecutive losses
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
// Initialize indicators
fastMAHandle = iMA(_Symbol, PERIOD_CURRENT, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
slowMAHandle = iMA(_Symbol, PERIOD_CURRENT, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
adxHandle = iADX(_Symbol, PERIOD_CURRENT, ADX_Period);
atrHandle = iATR(_Symbol, PERIOD_CURRENT, ATR_Period);
smaHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE); // 20-period
SMA
if(fastMAHandle == INVALID_HANDLE || slowMAHandle == INVALID_HANDLE ||
adxHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE || smaHandle ==
INVALID_HANDLE)
Print("Indicator initialization failed!");
return(INIT_FAILED);
[Link](MagicNumber);
[Link]();
[Link](ORDER_FILLING_FOK);
dynamicRiskPercent = RiskPercent; // Initialize dynamic risk
return(INIT_SUCCEEDED);
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
static datetime prevBar;
datetime currentBar = iTime(_Symbol, PERIOD_CURRENT, 0);
if(prevBar == currentBar) return;
prevBar = currentBar;
// Skip trades if volatility > 15 pips
double atrValue[1];
if (CopyBuffer(atrHandle, 0, 0, 1, atrValue) == 1 && atrValue[0] > 15 * _Point * 10)
Print("Volatility too high: ", atrValue[0]);
return;
// Skip trades if volatility < 10 pips
if (CopyBuffer(atrHandle, 0, 0, 1, atrValue) == 1 && atrValue[0] < 10 * _Point * 10)
Print("Low volatility: Skipping trade");
return;
// Adjust risk based on session and consecutive losses
AdjustSessionRisk();
if (consecutiveLosses >= 3) dynamicRiskPercent *= 0.7; // Reduce risk after 3 losses
// Check trading conditions
if(!IsTradingTime() || !IsStrongTrend() || !IsSpreadOK() || !IsTickValueValid()) return;
// Get indicator values
double fastMA[2], slowMA[2];
if(CopyBuffer(fastMAHandle, 0, 0, 2, fastMA) != 2 ||
CopyBuffer(slowMAHandle, 0, 0, 2, slowMA) != 2)
Print("Failed to copy MA values");
return;
// Check crossover (only short trades)
bool sellSignal = (fastMA[0] < slowMA[0]) && (fastMA[1] >= slowMA[1]);
if(sellSignal)
CloseAllPositions();
ExecuteTrade(ORDER_TYPE_SELL);
// Manage open positions
if(UseTrailingStop) CheckTrailingStop();
//+------------------------------------------------------------------+
//| Enhanced trading filters |
//+------------------------------------------------------------------+
bool IsTradingTime()
MqlDateTime timeCurrent;
TimeCurrent(timeCurrent);
// Trade during London + NY overlap (07:00-16:00 GMT)
return ([Link] >= 7 && [Link] < 16);
bool IsStrongTrend()
double adxValue[1], sma20[1];
if (CopyBuffer(adxHandle, 0, 0, 1, adxValue) != 1 ||
CopyBuffer(smaHandle, 0, 0, 1, sma20) != 1) return false;
double closePrice = iClose(_Symbol, PERIOD_CURRENT, 0); // Get current close price
return (adxValue[0] >= MinADX && closePrice < sma20[0]); // ADX + SMA filter
bool IsSpreadOK()
long spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
return spread <= MaxSpread;
bool IsTickValueValid()
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
return (tickValue > 0);
//+------------------------------------------------------------------+
//| Dynamic Position Sizing |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
double balance = [Link]();
if(balance <= 0) return 0;
// Volatility adjustment (scale down risk when ATR > average)
double atrCurrent[1], atr30[30];
if (CopyBuffer(atrHandle, 0, 0, 1, atrCurrent) != 1 ||
CopyBuffer(atrHandle, 0, 0, 30, atr30) != 30)
Print("Failed to copy ATR values");
return 0;
double atrRatio = atrCurrent[0] / ArrayAverage(atr30);
double adjustedRisk = dynamicRiskPercent;
// Reduce risk by 50% if volatility is 150%+ of average
if(atrRatio >= 1.5) adjustedRisk *= 0.5;
// 1:1 Leverage Constraint
double contractSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE);
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double maxLeverageLots = balance / (contractSize * price);
// Risk-Based Lots
double stopPoints = CalculateStops();
if (stopPoints <= 0) return 0; // Guard against invalid stops
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double riskLots = (balance * adjustedRisk / 100) / (stopPoints * tickValue);
// Final Lot Size (respect both leverage and risk)
double lots = MathMin(maxLeverageLots, riskLots);
// Apply Broker Constraints
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
// Normalize to Broker's Lot Step
if (lotStep > 0) {
lots = MathRound(lots / lotStep) * lotStep;
lots = NormalizeDouble(lots, (int)-MathLog10(lotStep)); // Dynamic decimal places
// Clamp to Min/Max
lots = MathMax(lots, minLot);
lots = MathMin(lots, maxLot);
// Final Validation
if (lots < minLot || lots > maxLot) {
Print("Invalid lot size: ", lots, " (Min: ", minLot, ", Max: ", maxLot, ")");
return 0;
return lots;
//+------------------------------------------------------------------+
//| Execute Trade with Dynamic RR |
//+------------------------------------------------------------------+
void ExecuteTrade(ENUM_ORDER_TYPE orderType)
{
double lotSize = CalculateLotSize();
if(lotSize <= 0) return;
double price = orderType == ORDER_TYPE_BUY ?
SymbolInfoDouble(_Symbol, SYMBOL_ASK) :
SymbolInfoDouble(_Symbol, SYMBOL_BID);
double stopLoss = CalculateStops();
double takeProfit = stopLoss * 2.0; // RR = 1:2
if(orderType == ORDER_TYPE_BUY)
stopLoss = NormalizeDouble(price - stopLoss, _Digits);
takeProfit = NormalizeDouble(price + takeProfit, _Digits);
else
stopLoss = NormalizeDouble(price + stopLoss, _Digits);
takeProfit = NormalizeDouble(price - takeProfit, _Digits);
// Validate stops
if(stopLoss <= 0 || takeProfit <= 0)
Print("Invalid stop levels: SL=", stopLoss, ", TP=", takeProfit);
return;
// Execute trade
[Link](ORDER_FILLING_IOC);
if()
{
Print("Trade execution failed: ", [Link]());
consecutiveLosses++; // Increment consecutive losses
else
Print("Trade executed: ", EnumToString(orderType), " ", lotSize, " lots at ", price,
" SL=", stopLoss, " TP=", takeProfit);
consecutiveLosses = 0; // Reset consecutive losses
//+------------------------------------------------------------------+
//| Helper Functions |
//+------------------------------------------------------------------+
double ArrayAverage(double &arr[])
double sum = 0;
for(int i=0; i<ArraySize(arr); i++) sum += arr[i];
return sum / ArraySize(arr);
double CalculateStops()
double atrBuffer[1];
if (CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) != 1) return 0;
return MathMax(atrBuffer[0] * ATR_Multiplier, 15 * _Point * 10); // Min 15 pips
void CloseAllPositions()
{
for(int i = PositionsTotal()-1; i >= 0; i--)
ulong ticket = PositionGetTicket(i);
if(ticket > 0 && PositionSelectByTicket(ticket))
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
[Link](ticket);
void CheckTrailingStop()
for(int i = PositionsTotal()-1; i >= 0; i--)
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
double currentSl = PositionGetDouble(POSITION_SL);
double priceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
double currentPrice = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ?
SymbolInfoDouble(_Symbol, SYMBOL_BID) :
SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double newSl = currentSl;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
if(currentPrice - priceOpen >= TrailStart * _Point)
{
newSl = currentPrice - TrailStep * _Point;
newSl = MathMax(newSl, currentSl);
else
if(priceOpen - currentPrice >= TrailStart * _Point)
newSl = currentPrice + TrailStep * _Point;
newSl = MathMin(newSl, currentSl);
if(newSl != currentSl)
[Link](ticket, newSl, PositionGetDouble(POSITION_TP));
//+------------------------------------------------------------------+
//| Session-Specific Risk Adjustment |
//+------------------------------------------------------------------+
void AdjustSessionRisk()
MqlDateTime timeCurrent;
TimeCurrent(timeCurrent);
// London/NY overlap (07:00-16:00 GMT): Max risk
if([Link] >= 7 && [Link] < 16) {
dynamicRiskPercent = 1.0; // Full risk
// Asian session: Reduced risk
else if([Link] >= 22 || [Link] < 5) {
dynamicRiskPercent = 0.3; // Reduced risk
// Other times: Base risk
else {
dynamicRiskPercent = 0.5; // Base risk
//+------------------------------------------------------------------+