IC Markets

EA using exponencial money management.

Share, develop, and backtest custom MQL4/MQL5 Expert Advisors, Python data-scraping scripts, trading bots, and automated market alert systems.
Post Reply
PTScalper
Site Admin
Posts: 302
Joined: Mon Jul 20, 2026 1:28 pm

EA using exponencial money management.

Post by PTScalper »

Hey everyone!

If you are new to trading, you've probably heard people say you should "never risk more than 1% of your account per trade." But have you ever actually done the math on what happens when you do that consistently?

It creates something called exponential growth—and it's the secret sauce that turns small accounts into big ones.

The Magic of the "Hockey Stick" Curve

Let’s say you have a $1,000 account.

The Rookie Way (Linear): You decide to always trade 0.10 lots. Whether you win or lose, your trade size stays exactly the same. Your account grows in a slow, straight line.

The Pro Way (Exponential): You decide to risk exactly 1% of your account balance on every trade.

On trade #1, your balance is $1,000, so you risk $10 (maybe 0.10 lots).

Fast forward... your account grows to $2,000.

Now, 1% risk is $20. Without changing your strategy, your trade size automatically increases to 0.20 lots.

Because your wins are constantly buying you larger lot sizes for the next trade, your growth curve eventually bends upward like a hockey stick. Albert Einstein supposedly called compounding the "8th wonder of the world" because the math gets so crazy so fast!

The Problem: Doing the Math is Slow!

When you are scalping on the 1-minute chart, you don't have time to pull out a calculator, check your new account balance, figure out the pip value, and type in a new lot size before the setup disappears.

The Solution: An Auto-Compounding EA
I’ve shared a free MT4 Expert Advisor (EA) in this thread. It trades a simple Moving Average Crossover strategy, but its real power is the auto-lot calculator built inside it.

Every single time the EA spots a trade, it:

Checks your live account balance.

Calculates exactly how many lots you need to risk your chosen percentage (e.g., 1%).

Executes the trade instantly.

You never have to type in a lot size again. Just set your risk to 1% or 2%, let the EA catch the crossovers, and let the 8th wonder of the world do the heavy lifting!

Grab the code from the main post above, compile it in MetaEditor, and drop it on a demo chart to watch it work!
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 302
Joined: Mon Jul 20, 2026 1:28 pm

Re: EA using exponencial money management.

Post by PTScalper »

How This EA Harnesses Exponential Growth

1.) Dynamic Position Sizing: Every time a new signal triggers, the EA checks your live AccountEquity() and recalculates your lot size based on your exact RiskPercent.
2.) Automatic Scaling: As your account balance climbs, your trade volume scales up proportionately without you having to reconfigure inputs.
3.) Bar Close Execution: It only evaluates entry signals when a candle closes to prevent "whipsaws" and false signals during high volatility.

MQL4 Expert Advisor Code

Code: Select all

//+------------------------------------------------------------------+
//|                                     AutoCompound_Scalper_EA.mq4  |
//+------------------------------------------------------------------+
#property strict

//--- Strategy Settings
input string   StrategyGroup     = "=== Strategy Settings ===";
input int      FastMA_Period     = 9;           // Fast EMA Period
input int      SlowMA_Period     = 21;          // Slow EMA Period
input ENUM_MA_METHOD MA_Method   = MODE_EMA;    // Moving Average Method

//--- Compounding & Risk Settings
input string   RiskGroup         = "=== Compounding & Risk ===";
input double   RiskPercent       = 1.0;         // Risk % of Equity per trade
input int      StopLossPips      = 15;          // Stop Loss in Pips
input int      TakeProfitPips    = 30;          // Take Profit in Pips

//--- EA Identification & Execution
input string   GeneralGroup      = "=== General Settings ===";
input int      MagicNumber       = 884422;      // Unique EA Identifier
input int      Slippage          = 3;           // Max Slippage in Points
input bool     TradeOnBarClose   = true;        // Execute only on candle close

//--- Global Tracking Variables
datetime lastBarTime;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    lastBarTime = 0;
    Print("AutoCompound Scalper EA initialized successfully.");
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    // 1. Ensure execution only happens once per closed candle (if enabled)
    if(TradeOnBarClose)
    {
        datetime currentBarTime = iTime(_Symbol, _Period, 0);
        if(currentBarTime == lastBarTime) return;
        lastBarTime = currentBarTime;
    }

    // 2. Do not open new orders if a trade is already active for this EA
    if(HasOpenPosition()) return;

    // 3. Strategy Indicator Signals (Fast EMA crossing Slow EMA on closed bars)
    double fastMA1 = iMA(_Symbol, _Period, FastMA_Period, 0, MA_Method, PRICE_CLOSE, 1);
    double slowMA1 = iMA(_Symbol, _Period, SlowMA_Period, 0, MA_Method, PRICE_CLOSE, 1);
    double fastMA2 = iMA(_Symbol, _Period, FastMA_Period, 0, MA_Method, PRICE_CLOSE, 2);
    double slowMA2 = iMA(_Symbol, _Period, SlowMA_Period, 0, MA_Method, PRICE_CLOSE, 2);

    bool buySignal  = (fastMA2 <= slowMA2 && fastMA1 > slowMA1);
    bool sellSignal = (fastMA2 >= slowMA2 && fastMA1 < slowMA1);

    if(!buySignal && !sellSignal) return;

    // 4. Adjust points/pips for 3/5-digit brokers
    double point = Point;
    int digits = Digits;
    int calcSL = StopLossPips;
    int calcTP = TakeProfitPips;

    if(digits == 3 || digits == 5)
    {
        calcSL *= 10;
        calcTP *= 10;
    }

    // 5. Calculate dynamically compounded lot size
    double lotSize = CalculateLotSize(calcSL);
    if(lotSize <= 0) return;

    // 6. Execute Orders
    if(buySignal)
    {
        double ask = MarketInfo(_Symbol, MODE_ASK);
        double sl = (calcSL > 0) ? ask - (calcSL * point) : 0;
        double tp = (calcTP > 0) ? ask + (calcTP * point) : 0;

        int ticket = OrderSend(_Symbol, OP_BUY, lotSize, ask, Slippage, sl, tp, "Compounding Buy", MagicNumber, 0, clrGreen);
        
        if(ticket > 0)
            Print("Buy Order #", ticket, " opened. Volume: ", lotSize, " lots at ", RiskPercent, "% equity risk.");
        else
            Print("Error opening Buy order: #", GetLastError());
    }
    else if(sellSignal)
    {
        double bid = MarketInfo(_Symbol, MODE_BID);
        double sl = (calcSL > 0) ? bid + (calcSL * point) : 0;
        double tp = (calcTP > 0) ? bid - (calcTP * point) : 0;

        int ticket = OrderSend(_Symbol, OP_SELL, lotSize, bid, Slippage, sl, tp, "Compounding Sell", MagicNumber, 0, clrRed);
        
        if(ticket > 0)
            Print("Sell Order #", ticket, " opened. Volume: ", lotSize, " lots at ", RiskPercent, "% equity risk.");
        else
            Print("Error opening Sell order: #", GetLastError());
    }
}

//+------------------------------------------------------------------+
//| Dynamic Compounding Lot Size Formula                             |
//+------------------------------------------------------------------+
double CalculateLotSize(int slPoints)
{
    if(slPoints <= 0) return MarketInfo(_Symbol, MODE_MINLOT);

    // Get current equity and compute dollar amount to risk
    double equity = AccountEquity();
    double riskAmount = equity * (RiskPercent / 100.0);

    // Get value of 1 tick in account currency
    double tickValue = MarketInfo(_Symbol, MODE_TICKVALUE);
    if(tickValue <= 0)
    {
        Print("Error: Could not retrieve valid Tick Value.");
        return 0;
    }

    // Raw lot calculation: Risk Amount / (SL in points * Tick Value)
    double rawLots = riskAmount / (slPoints * tickValue);

    // Broker normalization
    double minLot  = MarketInfo(_Symbol, MODE_MINLOT);
    double maxLot  = MarketInfo(_Symbol, MODE_MAXLOT);
    double lotStep = MarketInfo(_Symbol, MODE_LOTSTEP);

    // Round down to the nearest step to prevent exceeding risk limit
    double finalLots = MathFloor(rawLots / lotStep) * lotStep;
    finalLots = MathMax(minLot, MathMin(maxLot, finalLots));

    return finalLots;
}

//+------------------------------------------------------------------+
//| Check if an active position exists with this EA's Magic Number   |
//+------------------------------------------------------------------+
bool HasOpenPosition()
{
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == _Symbol && OrderMagicNumber() == MagicNumber)
            {
                if(OrderType() == OP_BUY || OrderType() == OP_SELL)
                    return true;
            }
        }
    }
    return false;
}
How to Install and Run It

1.) Open MetaTrader 4 and press F4 to open MetaEditor.
2.) In the Navigator pane, right-click the Experts folder $\rightarrow$ click New Expert Advisor (template) $\rightarrow$ name it AutoCompound_Scalper_EA.
3.) Replace all default text with the code above and click Compile (or press F7).Return to MT4, make sure the AutoTrading button at the top toolbar is green (enabled).
4.) Drag the EA from the Navigator $\rightarrow$ Expert Advisors pane onto any 1-minute (M1) or 5-minute (M5) chart.
5.) In the settings pop-up under the Common tab, check "Allow live trading" and click OK.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 302
Joined: Mon Jul 20, 2026 1:28 pm

Re: EA using exponencial money management.

Post by PTScalper »

Here i prepared version for MT5 traders:

MetaTrader 5 (MQL5)

MT5 handles indicators differently than MT4. Instead of calculating the Moving Average on every tick, MT5 creates an indicator "handle" once when the EA loads, and we just copy the data from its buffer when a candle closes.

How to use it:

1.) Open MetaEditor in MT5 (F4).

2.) Right-click Experts -> New Expert Advisor (template) -> Name it AutoCompound_Scalper_MT5.

3.) Paste the code, click Compile, and drag it onto your chart.

Code: Select all

//+------------------------------------------------------------------+
//|                                     AutoCompound_Scalper_MT5.mq5 |
//+------------------------------------------------------------------+
#property strict

#include <Trade\Trade.mqh> // MT5 Trade Library

//--- Strategy Settings
input string   StrategyGroup     = "=== Strategy Settings ===";
input int      FastMA_Period     = 9;           
input int      SlowMA_Period     = 21;          
input ENUM_MA_METHOD MA_Method   = MODE_EMA;    

//--- Compounding & Risk Settings
input string   RiskGroup         = "=== Compounding & Risk ===";
input double   RiskPercent       = 1.0;         // Risk % of Equity
input int      StopLossPips      = 15;          
input int      TakeProfitPips    = 30;          

//--- General Settings
input string   GeneralGroup      = "=== General Settings ===";
input int      MagicNumber       = 884422;      
input int      Slippage          = 3;           

//--- Global Variables
CTrade         trade;
int            fastMaHandle;
int            slowMaHandle;
datetime       lastBarTime;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Initialize Trade Class with Magic Number and Slippage
    trade.SetExpertMagicNumber(MagicNumber);
    trade.SetDeviationInPoints(Slippage);

    // Get Indicator Handles
    fastMaHandle = iMA(_Symbol, _Period, FastMA_Period, 0, MA_Method, PRICE_CLOSE);
    slowMaHandle = iMA(_Symbol, _Period, SlowMA_Period, 0, MA_Method, PRICE_CLOSE);

    if(fastMaHandle == INVALID_HANDLE || slowMaHandle == INVALID_HANDLE)
    {
        Print("Error creating indicator handles.");
        return(INIT_FAILED);
    }
    
    lastBarTime = 0;
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    // 1. Execute only on Bar Close
    datetime currentBarTime = (datetime)SeriesInfoInteger(_Symbol, PERIOD_CURRENT, SERIES_LASTBAR_DATE);
    if(currentBarTime == lastBarTime) return;

    // 2. Do not open new orders if a position is already active
    if(HasOpenPosition()) return;

    // 3. Get Indicator Values for the last 2 closed candles (Index 1 and 2)
    double fastMA[], slowMA[];
    CopyBuffer(fastMaHandle, 0, 1, 2, fastMA); 
    CopyBuffer(slowMaHandle, 0, 1, 2, slowMA); 
    
    // In MQL5 CopyBuffer (without ArraySetAsSeries): [0] is older candle, [1] is newer closed candle
    bool buySignal  = (fastMA[0] <= slowMA[0] && fastMA[1] > slowMA[1]);
    bool sellSignal = (fastMA[0] >= slowMA[0] && fastMA[1] < slowMA[1]);

    if(!buySignal && !sellSignal) return;
    
    // We update lastBarTime only if we had a signal to process, or you can update it unconditionally
    lastBarTime = currentBarTime;

    // 4. Calculate dynamically compounded lot size
    double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
    int calcSL = (digits == 3 || digits == 5) ? StopLossPips * 10 : StopLossPips;
    int calcTP = (digits == 3 || digits == 5) ? TakeProfitPips * 10 : TakeProfitPips;

    double lotSize = CalculateLotSize(calcSL);
    if(lotSize <= 0) return;

    // 5. Execute Orders
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

    if(buySignal)
    {
        double sl = (calcSL > 0) ? ask - (calcSL * point) : 0;
        double tp = (calcTP > 0) ? ask + (calcTP * point) : 0;
        trade.Buy(lotSize, _Symbol, ask, sl, tp, "AutoCompound Buy");
    }
    else if(sellSignal)
    {
        double sl = (calcSL > 0) ? bid + (calcSL * point) : 0;
        double tp = (calcTP > 0) ? bid - (calcTP * point) : 0;
        trade.Sell(lotSize, _Symbol, bid, sl, tp, "AutoCompound Sell");
    }
}

//+------------------------------------------------------------------+
//| Dynamic Compounding Lot Size Formula                             |
//+------------------------------------------------------------------+
double CalculateLotSize(int slPoints)
{
    if(slPoints <= 0) return SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);

    double equity = AccountInfoDouble(ACCOUNT_EQUITY);
    double riskAmount = equity * (RiskPercent / 100.0);
    double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    
    if(tickValue <= 0) return 0;

    double rawLots = riskAmount / (slPoints * tickValue);
    double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

    double finalLots = MathFloor(rawLots / lotStep) * lotStep;
    return MathMax(minLot, MathMin(maxLot, finalLots));
}

//+------------------------------------------------------------------+
//| Check if an active position exists                               |
//+------------------------------------------------------------------+
bool HasOpenPosition()
{
    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong ticket = PositionGetTicket(i);
        if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
        {
            return true;
        }
    }
    return false;
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 302
Joined: Mon Jul 20, 2026 1:28 pm

Re: EA using exponencial money management.

Post by PTScalper »

cTrader (C#)

cTrader makes this incredibly clean. C# has a native OnBar() method, meaning we don't have to write messy logic to check if a candle has closed. The bot automatically waits and runs the code exactly when the bar finishes painting.

How to use it:

1.) Open cTrader, go to the Automate tab.

2.) Click New cBot and name it AutoCompoundScalper.

3.) Paste this code, click Build (the hammer icon), and add it to your chart.

Code: Select all

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class AutoCompoundScalper_cBot : Robot
    {
        //--- Strategy Parameters
        [Parameter("Fast EMA Period", Group = "Strategy", DefaultValue = 9, MinValue = 1)]
        public int FastMaPeriod { get; set; }

        [Parameter("Slow EMA Period", Group = "Strategy", DefaultValue = 21, MinValue = 1)]
        public int SlowMaPeriod { get; set; }

        //--- Compounding & Risk Parameters
        [Parameter("Risk Percent (%)", Group = "Compounding & Risk", DefaultValue = 1.0, MinValue = 0.1)]
        public double RiskPercent { get; set; }

        [Parameter("Stop Loss (Pips)", Group = "Compounding & Risk", DefaultValue = 15.0, MinValue = 1.0)]
        public double StopLossPips { get; set; }

        [Parameter("Take Profit (Pips)", Group = "Compounding & Risk", DefaultValue = 30.0, MinValue = 0.0)]
        public double TakeProfitPips { get; set; }

        //--- Bot Identification
        [Parameter("Instance Label", Group = "General", DefaultValue = "AutoCompoundScalper")]
        public string BotLabel { get; set; }

        //--- Indicator References
        private ExponentialMovingAverage _fastMa;
        private ExponentialMovingAverage _slowMa;

        protected override void OnStart()
        {
            // Initialize the Moving Averages on the current chart's close prices
            _fastMa = Indicators.ExponentialMovingAverage(Bars.ClosePrices, FastMaPeriod);
            _slowMa = Indicators.ExponentialMovingAverage(Bars.ClosePrices, SlowMaPeriod);

            Print("AutoCompound Scalper cBot started successfully on {0}", SymbolName);
        }

        // OnBar is called once every time a new candle opens (meaning the previous bar just closed)
        protected override void OnBar()
        {
            // 1. Ensure sufficient history is loaded
            if (Bars.Count < SlowMaPeriod + 2) return;

            // 2. Prevent stacking: do not open new orders if one is already active for this bot
            var activePositions = Positions.FindAll(BotLabel, SymbolName);
            if (activePositions.Length > 0) return;

            // 3. Strategy Signals (Check the crossover on closed candles: Index 1 and Index 2)
            double fastPrev  = _fastMa.Result.Last(1);  // Just closed candle
            double slowPrev  = _slowMa.Result.Last(1);
            double fastPrior = _fastMa.Result.Last(2);  // 2 candles ago
            double slowPrior = _slowMa.Result.Last(2);

            bool buySignal  = (fastPrior <= slowPrior && fastPrev > slowPrev);
            bool sellSignal = (fastPrior >= slowPrior && fastPrev < slowPrev);

            if (!buySignal && !sellSignal) return;

            // 4. Calculate dynamic compounding volume
            double volumeInUnits = CalculateVolume();
            if (volumeInUnits <= 0) return;

            // 5. Execute Order
            if (buySignal)
            {
                var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, volumeInUnits, BotLabel, StopLossPips, TakeProfitPips);
                if (result.IsSuccessful)
                {
                    Print("Buy Order opened! Volume: {0} units at {1}% risk.", volumeInUnits, RiskPercent);
                }
                else
                {
                    Print("Buy Order failed: {0}", result.Error);
                }
            }
            else if (sellSignal)
            {
                var result = ExecuteMarketOrder(TradeType.Sell, SymbolName, volumeInUnits, BotLabel, StopLossPips, TakeProfitPips);
                if (result.IsSuccessful)
                {
                    Print("Sell Order opened! Volume: {0} units at {1}% risk.", volumeInUnits, RiskPercent);
                }
                else
                {
                    Print("Sell Order failed: {0}", result.Error);
                }
            }
        }

        // Calculates volume in units based on exact account equity risk
        private double CalculateVolume()
        {
            if (StopLossPips <= 0) return 0;

            // Dollar amount we are willing to risk on this trade
            double riskAmount = Account.Equity * (RiskPercent / 100.0);

            // Formula: Units = Risk / (SL in Pips * Value of 1 Pip for 1 Unit)
            double rawVolume = riskAmount / (StopLossPips * Symbol.PipValue);

            // Normalize volume to broker requirements (rounded down so risk is never exceeded)
            double normalizedVolume = Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);

            if (normalizedVolume < Symbol.VolumeInUnitsMin)
            {
                Print("Calculated volume ({0}) is below broker minimum ({1}).", normalizedVolume, Symbol.VolumeInUnitsMin);
                return 0;
            }

            if (normalizedVolume > Symbol.VolumeInUnitsMax)
            {
                normalizedVolume = Symbol.VolumeInUnitsMax;
            }

            return normalizedVolume;
        }
    }
}
Key Features of this cBot

1.) Dynamic Equity Compounding: Calculates volume based on your live account equity and Stop Loss distance on every new trade.

2.) Bar-Close Execution: Uses cTrader’s native OnBar() event to eliminate intraday whipsaws and execute only on confirmed candle closes.

3.) Position Protection: Checks if a trade with the bot's label is already open on the current pair before entering a new one.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply