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!
EA using exponencial money management.
EA using exponencial money management.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: EA using exponencial money management.
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
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.
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;
}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.
Re: EA using exponencial money management.
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.
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.
Re: EA using exponencial money management.
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.
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.
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;
}
}
}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.