Scaling rules after payout — keeping challenge habits on funded
Scaling rules after payout — keeping challenge habits on funded
Getting a payout feels like permission to loosen. That is exactly when funded accounts start looking like challenge accounts in reverse — size up, stretch rules, “I earned this.” I treat post-payout as a high-risk psychology window, not a victory lap.
Challenge habits that stay after payout:
1. Same risk per trade band I used to pass (or slightly tighter for the first two weeks funded). Passing did not invent a new edge.
2. Same daily hard stop relative to account rules — still under firm DD, still written before the open.
3. Same news blackout and session shortlist. Payout does not unlock NFP gambling.
4. Same journaling fields. If anything, I add a “urge to celebrate with size” tag for two weeks.
Scaling rules I actually use after payout:
1. No size increase on the day of payout or the next session. Cool-down is mandatory.
2. Scale only after a pre-defined sample of funded process days (for me: consecutive sessions with soft-stop compliance and no C setups) — not after one green day.
3. Increase in small steps (e.g. 0.25% → 0.3% → 0.35%), never a jump to “comfortable” lots.
4. If trailing or static DD floor is tight after a withdrawal, size from the new effective cushion first — see my trailing-DD notes separately.
5. First violation of challenge-era rules after payout → immediate return to challenge size for N sessions.
What I refuse:
- “House money” framing. The balance is the firm’s risk capital plus your rules. House money language is how people donate payouts back.
- Adding pairs or sessions I did not trade in the challenge just because funded feels freer.
- Trading through the soft mental stop because “I’m funded now, I can handle it.”
Practical week-one funded template: trade the exact playbook that passed. Screenshot the risk % each morning. End of week: if process scores match challenge quality, consider a micro step-up. If process slipped, keep size flat and fix selection.
Payout is a cash event. Edge is a process event. Keep challenge habits until the journal proves you still deserve the size you already have — then scale slowly.
Challenge habits that stay after payout:
1. Same risk per trade band I used to pass (or slightly tighter for the first two weeks funded). Passing did not invent a new edge.
2. Same daily hard stop relative to account rules — still under firm DD, still written before the open.
3. Same news blackout and session shortlist. Payout does not unlock NFP gambling.
4. Same journaling fields. If anything, I add a “urge to celebrate with size” tag for two weeks.
Scaling rules I actually use after payout:
1. No size increase on the day of payout or the next session. Cool-down is mandatory.
2. Scale only after a pre-defined sample of funded process days (for me: consecutive sessions with soft-stop compliance and no C setups) — not after one green day.
3. Increase in small steps (e.g. 0.25% → 0.3% → 0.35%), never a jump to “comfortable” lots.
4. If trailing or static DD floor is tight after a withdrawal, size from the new effective cushion first — see my trailing-DD notes separately.
5. First violation of challenge-era rules after payout → immediate return to challenge size for N sessions.
What I refuse:
- “House money” framing. The balance is the firm’s risk capital plus your rules. House money language is how people donate payouts back.
- Adding pairs or sessions I did not trade in the challenge just because funded feels freer.
- Trading through the soft mental stop because “I’m funded now, I can handle it.”
Practical week-one funded template: trade the exact playbook that passed. Screenshot the risk % each morning. End of week: if process scores match challenge quality, consider a micro step-up. If process slipped, keep size flat and fix selection.
Payout is a cash event. Edge is a process event. Keep challenge habits until the journal proves you still deserve the size you already have — then scale slowly.
- Attachments
-
- 27-post-payout-scaling-sketch.png (102.34 KiB) Viewed 21 times
It’s Fairman 
Re: Scaling rules after payout — keeping challenge habits on funded
When you are executing high-volume scalps, scaling up out of celebration rather than statistical backing is fatal. The edge that got you the payout was calibrated to a specific risk parameter and a specific psychological baseline. Altering the position sizing just because the account balance crossed a threshold breaks that calibration completely.Fairman wrote: Sat Sep 05, 2026 5:28 pm Getting a payout feels like permission to loosen. That is exactly when funded accounts start looking like challenge accounts in reverse — size up, stretch rules, “I earned this.” I treat post-payout as a high-risk psychology window, not a victory lap.
Challenge habits that stay after payout:
1. Same risk per trade band I used to pass (or slightly tighter for the first two weeks funded). Passing did not invent a new edge.
2. Same daily hard stop relative to account rules — still under firm DD, still written before the open.
3. Same news blackout and session shortlist. Payout does not unlock NFP gambling.
4. Same journaling fields. If anything, I add a “urge to celebrate with size” tag for two weeks.
Scaling rules I actually use after payout:
1. No size increase on the day of payout or the next session. Cool-down is mandatory.
2. Scale only after a pre-defined sample of funded process days (for me: consecutive sessions with soft-stop compliance and no C setups) — not after one green day.
3. Increase in small steps (e.g. 0.25% → 0.3% → 0.35%), never a jump to “comfortable” lots.
4. If trailing or static DD floor is tight after a withdrawal, size from the new effective cushion first — see my trailing-DD notes separately.
5. First violation of challenge-era rules after payout → immediate return to challenge size for N sessions.
What I refuse:
- “House money” framing. The balance is the firm’s risk capital plus your rules. House money language is how people donate payouts back.
- Adding pairs or sessions I did not trade in the challenge just because funded feels freer.
- Trading through the soft mental stop because “I’m funded now, I can handle it.”
Practical week-one funded template: trade the exact playbook that passed. Screenshot the risk % each morning. End of week: if process scores match challenge quality, consider a micro step-up. If process slipped, keep size flat and fix selection.
Payout is a cash event. Edge is a process event. Keep challenge habits until the journal proves you still deserve the size you already have — then scale slowly.
Your point about the "urge to celebrate with size" tag in the journal is brilliant. It forces you to quantify an emotional impulse.
I’ve found that the best way to handle the post-payout danger zone is to remove the human element entirely. Instead of relying on willpower to maintain challenge-era sizing, I hardcode the cool-down phase into my charts. If the script says my risk is capped at 0.25% because I'm in a post-withdrawal window, the math doesn't care how confident I feel about a setup.
Pine Script: Post-Payout Risk Enforcer
To complement those strict scaling rules, here is a Pine Script (v5) utility. It creates a visual risk-management dashboard directly on the chart. It calculates exact lot sizes based on a strict daily drawdown limit and features a toggleable "Post-Payout Cooldown Mode" that automatically halves your standard risk to enforce that mandatory cool-down phase.
Code: Select all
//@version=5
indicator("Post-Payout Risk Manager", overlay=true)
// =========================================================================
// INPUTS: Account & Risk Parameters
// =========================================================================
grp_acct = "Account Settings"
acct_balance = input.float(100000, title="Current Account Balance ($)", group=grp_acct)
daily_dd_limit = input.float(3.0, title="Firm Daily DD Limit (%)", step=0.5, group=grp_acct)
grp_risk = "Risk Sizing & Rules"
base_risk_pct = input.float(0.5, title="Base Risk per Trade (%)", step=0.05, group=grp_risk)
cooldown_mode = input.bool(true, title="Enable Post-Payout Cooldown (Halves Risk)", group=grp_risk)
sl_pips = input.float(10.0, title="Expected Stop Loss (Pips/Points)", step=0.5, group=grp_risk)
pip_value = input.float(10.0, title="Value per Pip (Standard Lot)", group=grp_risk)
// =========================================================================
// CALCULATIONS
// =========================================================================
// Enforce post-payout sizing (cuts risk in half if cooldown mode is active)
active_risk_pct = cooldown_mode ? (base_risk_pct * 0.5) : base_risk_pct
// Calculate dollar values
risk_dollar_amount = acct_balance * (active_risk_pct / 100)
daily_dd_dollar = acct_balance * (daily_dd_limit / 100)
// Calculate position size (Lots)
position_size = risk_dollar_amount / (sl_pips * pip_value)
// =========================================================================
// DASHBOARD DISPLAY
// =========================================================================
var table risk_panel = table.new(position.bottom_right, 2, 5, border_width=1, border_color=color.gray)
if barstate.islast
// Header
table.cell(risk_panel, 0, 0, "RISK ENFORCER", text_color=color.white, bgcolor=color.new(color.blue, 30), colspan=2)
// Account Size
table.cell(risk_panel, 0, 1, "Account Size:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 1, "$" + str.tostring(acct_balance, "#.##"), text_color=color.white, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
// Active Risk (Highlights in Orange if Cooldown is active)
risk_color = cooldown_mode ? color.orange : color.white
table.cell(risk_panel, 0, 2, cooldown_mode ? "Cooldown Risk %:" : "Active Risk %:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 2, str.tostring(active_risk_pct) + "%", text_color=risk_color, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
// Risk in Dollars
table.cell(risk_panel, 0, 3, "Trade Risk Amount:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 3, "$" + str.tostring(risk_dollar_amount, "#.##"), text_color=color.red, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
// Output Lot Size
table.cell(risk_panel, 0, 4, "Allowed Size (Lots):", text_color=color.white, bgcolor=color.new(color.black, 0), text_halign=text.align_left)
table.cell(risk_panel, 1, 4, str.tostring(position_size, "#.##"), text_color=color.green, bgcolor=color.new(color.black, 0), text_halign=text.align_right)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
How the Script Aligns with the Post:
Cooldown Enforcement: The cooldown_mode boolean makes it mathematically impossible to "size up" out of excitement. By default, it slashes the base risk when active.
Visualizing the Hard Stop: It keeps the account parameters front and center, meaning the daily firm DD limit is constantly visible before a trade is placed.
Micro-Stepping: The base_risk_pct variable allows for the exact micro-stepping mentioned (e.g., typing in 0.35% directly rather than guessing lot sizes).
Cooldown Enforcement: The cooldown_mode boolean makes it mathematically impossible to "size up" out of excitement. By default, it slashes the base risk when active.
Visualizing the Hard Stop: It keeps the account parameters front and center, meaning the daily firm DD limit is constantly visible before a trade is placed.
Micro-Stepping: The base_risk_pct variable allows for the exact micro-stepping mentioned (e.g., typing in 0.35% directly rather than guessing lot sizes).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
This version integrates the daily session data and projects your firm's hard stop limits directly onto the chart. By fetching the daily opening price, the script calculates exactly where your daily drawdown limit sits in terms of price action (assuming a position opened at the start of the session).
It plots visual boundaries so you can see your physical "blowout" levels for the day, and updates the dashboard with the remaining risk allowance.
Pine Script: Risk Manager & Daily DD Tracker
It plots visual boundaries so you can see your physical "blowout" levels for the day, and updates the dashboard with the remaining risk allowance.
Pine Script: Risk Manager & Daily DD Tracker
Code: Select all
//@version=5
indicator("Prop Firm Risk & Daily DD Dashboard", overlay=true)
// =========================================================================
// INPUTS: Account & Risk Parameters
// =========================================================================
grp_acct = "Account Settings"
acct_balance = input.float(100000, title="Start of Day Balance ($)", group=grp_acct)
daily_dd_limit = input.float(3.0, title="Firm Daily DD Limit (%)", step=0.5, group=grp_acct)
grp_risk = "Risk Sizing & Rules"
base_risk_pct = input.float(0.5, title="Base Risk per Trade (%)", step=0.05, group=grp_risk)
cooldown_mode = input.bool(true, title="Enable Post-Payout Cooldown (Halves Risk)", group=grp_risk)
sl_pips = input.float(10.0, title="Expected Stop Loss (Pips/Points)", step=0.5, group=grp_risk)
pip_value = input.float(10.0, title="Value per Pip (Standard Lot)", group=grp_risk)
// =========================================================================
// SESSION & DRAWDOWN CALCULATIONS
// =========================================================================
// Fetch today's opening price automatically
daily_open = request.security(syminfo.tickerid, "D", open, lookahead=barmerge.lookahead_on)
// Risk and Sizing Math
active_risk_pct = cooldown_mode ? (base_risk_pct * 0.5) : base_risk_pct
risk_dollar_amount = acct_balance * (active_risk_pct / 100)
daily_dd_dollar = acct_balance * (daily_dd_limit / 100)
position_size = risk_dollar_amount / (sl_pips * pip_value)
// Calculate max adverse excursion (in pips) before hitting the Daily DD limit
// based on the calculated position size.
max_dd_pips = daily_dd_dollar / (position_size * pip_value)
// Price levels where Daily DD is breached (if max position size was held from the open)
long_dd_breach_price = daily_open - (max_dd_pips * syminfo.mintick * 10)
short_dd_breach_price = daily_open + (max_dd_pips * syminfo.mintick * 10)
// Consecutive losses allowed today before breaching firm rules
trades_to_blowout = math.floor(daily_dd_dollar / risk_dollar_amount)
// =========================================================================
// CHART PLOTS
// =========================================================================
// Plot Daily Open
plot(daily_open, title="Daily Session Open", color=color.new(color.blue, 30), linewidth=2, style=plot.style_cross)
// Plot the Hard Stop Drawdown Levels
plot(long_dd_breach_price, title="Long DD Breach Level", color=color.new(color.red, 40), linewidth=1, style=plot.style_linebr)
plot(short_dd_breach_price, title="Short DD Breach Level", color=color.new(color.red, 40), linewidth=1, style=plot.style_linebr)
// =========================================================================
// DASHBOARD DISPLAY
// =========================================================================
var table risk_panel = table.new(position.bottom_right, 2, 8, border_width=1, border_color=color.rgb(43, 43, 43))
if barstate.islast
// Header
table.cell(risk_panel, 0, 0, "PROP FIRM RISK DASHBOARD", text_color=color.white, bgcolor=color.new(color.blue, 30), colspan=2)
// Account & Sizing Metrics
table.cell(risk_panel, 0, 1, "Start of Day Balance:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 1, "$" + str.tostring(acct_balance, "#.##"), text_color=color.white, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
risk_color = cooldown_mode ? color.orange : color.white
table.cell(risk_panel, 0, 2, cooldown_mode ? "Cooldown Risk %:" : "Active Risk %:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 2, str.tostring(active_risk_pct) + "%", text_color=risk_color, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
table.cell(risk_panel, 0, 3, "Trade Risk Amount:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 3, "$" + str.tostring(risk_dollar_amount, "#.##"), text_color=color.red, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
table.cell(risk_panel, 0, 4, "Allowed Size (Lots):", text_color=color.white, bgcolor=color.new(color.black, 0), text_halign=text.align_left)
table.cell(risk_panel, 1, 4, str.tostring(position_size, "#.##"), text_color=color.green, bgcolor=color.new(color.black, 0), text_halign=text.align_right)
// Daily DD Limits & Tracking
table.cell(risk_panel, 0, 5, "HARD STOP METRICS", text_color=color.white, bgcolor=color.new(color.red, 50), colspan=2)
table.cell(risk_panel, 0, 6, "Daily DD Limit:", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 6, "$" + str.tostring(daily_dd_dollar, "#.##"), text_color=color.red, bgcolor=color.new(color.black, 20), text_halign=text.align_right)
table.cell(risk_panel, 0, 7, "Bullets Left (Max Loss Trades):", text_color=color.gray, bgcolor=color.new(color.black, 20), text_halign=text.align_left)
table.cell(risk_panel, 1, 7, str.tostring(trades_to_blowout), text_color=color.yellow, bgcolor=color.new(color.black, 20), text_halign=text.align_right)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
Key Technical Additions:
Dynamic Session Pricing: request.security(syminfo.tickerid, "D", open) ensures the baseline for your daily limits automatically resets at the start of the trading day.
Visual Hard Stop Boundaries: The script translates your daily drawdown limit in dollars into a concrete price level (long_dd_breach_price and short_dd_breach_price). If the market crosses those red lines, you immediately know that the maximum allowed daily volume would have blown the account limit.
Bullets Left Metric: The table calculates exactly how many consecutive full-risk stop-outs you can take at your currently scaled lot size before the firm cuts the account. It adjusts automatically if cooldown_mode is enabled.
Dynamic Session Pricing: request.security(syminfo.tickerid, "D", open) ensures the baseline for your daily limits automatically resets at the start of the trading day.
Visual Hard Stop Boundaries: The script translates your daily drawdown limit in dollars into a concrete price level (long_dd_breach_price and short_dd_breach_price). If the market crosses those red lines, you immediately know that the maximum allowed daily volume would have blown the account limit.
Bullets Left Metric: The table calculates exactly how many consecutive full-risk stop-outs you can take at your currently scaled lot size before the firm cuts the account. It adjusts automatically if cooldown_mode is enabled.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
Plus i prepared version for Ctrader and MT5.
1. cTrader (C#) Implementation: Execution Gatekeeper
In cTrader, you handle this by hooking into the OnTick or OnBar events to track the start-of-day balance, and then wrapping your execution logic inside a validation method. If you are a high-volume scalper, keeping this inside an asynchronous execution wrapper prevents UI thread blocking.
1. cTrader (C#) Implementation: Execution Gatekeeper
In cTrader, you handle this by hooking into the OnTick or OnBar events to track the start-of-day balance, and then wrapping your execution logic inside a validation method. If you are a high-volume scalper, keeping this inside an asynchronous execution wrapper prevents UI thread blocking.
Code: Select all
using System;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PostPayoutRiskManager : Robot
{
[Parameter("Base Risk (%)", DefaultValue = 0.5, Group = "Risk")]
public double BaseRiskPct { get; set; }
[Parameter("Cooldown Mode (Halves Risk)", DefaultValue = true, Group = "Risk")]
public bool CooldownMode { get; set; }
[Parameter("Firm Daily DD Limit (%)", DefaultValue = 3.0, Group = "Limits")]
public double DailyDdLimitPct { get; set; }
private double _startOfDayBalance;
private int _currentDay = -1;
protected override void OnTick()
{
// 1. Anchor the Start of Day Balance
if (Server.Time.DayOfYear != _currentDay)
{
_startOfDayBalance = Account.Balance;
_currentDay = Server.Time.DayOfYear;
Print($"New Session: Balance Anchored at {_startOfDayBalance}");
}
// Optional: Active Fat-Finger Guard
// If equity breaches the limit mid-trade, flatten the account immediately.
if (!IsDrawdownCompliant())
{
foreach (var position in Positions)
{
ClosePositionAsync(position);
}
}
}
// 2. The Gatekeeper Method
private bool IsDrawdownCompliant()
{
double maxAllowedLoss = _startOfDayBalance * (DailyDdLimitPct / 100.0);
double currentLoss = _startOfDayBalance - Account.Equity;
return currentLoss < maxAllowedLoss;
}
// 3. Sizing Calculator
private double CalculateLotSize(double slPips)
{
double activeRisk = CooldownMode ? (BaseRiskPct * 0.5) : BaseRiskPct;
double riskAmount = Account.Balance * (activeRisk / 100.0);
// Formula: Risk Amount / (SL Pips * Pip Value)
double rawVolume = (riskAmount) / (slPips * Symbol.PipValue);
return Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
}
// 4. Execution Wrapper
public void RequestTrade(TradeType tradeType, double slPips)
{
if (!IsDrawdownCompliant())
{
Print("TRADE REJECTED: Daily Drawdown Limit Hit.");
return;
}
double volume = CalculateLotSize(slPips);
ExecuteMarketOrderAsync(tradeType, SymbolName, volume, "RiskManager", slPips, null);
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
2. MetaTrader 5 (MQL5) Implementation: Event-Driven Blocker
MQL5 requires slightly more manual state management for tick values and contract sizes, but the logic remains identical. We track the TimeCurrent() day, anchor the balance, and block the OrderSend execution.
MQL5 requires slightly more manual state management for tick values and contract sizes, but the logic remains identical. We track the TimeCurrent() day, anchor the balance, and block the OrderSend execution.
Code: Select all
//+------------------------------------------------------------------+
//| Inputs |
//+------------------------------------------------------------------+
input double InpBaseRiskPct = 0.5; // Base Risk (%)
input bool InpCooldownMode = true; // Cooldown Mode (Halves Risk)
input double InpDailyDDLimitPct = 3.0; // Firm Daily DD Limit (%)
double g_startOfDayBalance = 0.0;
int g_currentDay = -1;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
MqlDateTime timeStruct;
TimeCurrent(timeStruct);
// 1. Anchor the Start of Day Balance
if(timeStruct.day != g_currentDay)
{
g_startOfDayBalance = AccountInfoDouble(ACCOUNT_BALANCE);
g_currentDay = timeStruct.day;
Print("New Session Anchored. Balance: ", DoubleToString(g_startOfDayBalance, 2));
}
// Active limit breach check for open positions could be placed here
}
//+------------------------------------------------------------------+
//| Gatekeeper Logic |
//+------------------------------------------------------------------+
bool IsDrawdownCompliant()
{
if(g_startOfDayBalance <= 0) return false;
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
double maxAllowedLoss = g_startOfDayBalance * (InpDailyDDLimitPct / 100.0);
double currentLoss = g_startOfDayBalance - currentEquity;
if(currentLoss >= maxAllowedLoss)
{
Print("LOCKOUT: Daily DD Limit Breached.");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Sizing Logic |
//+------------------------------------------------------------------+
double CalculateLotSize(double slPips)
{
double activeRisk = InpCooldownMode ? (InpBaseRiskPct * 0.5) : InpBaseRiskPct;
double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * (activeRisk / 100.0);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
if(tickSize == 0 || tickValue == 0) return 0.0;
// Normalize pips to points based on broker digits
double points = slPips * (MathPow(10, _Digits) * tickSize);
double lossPerLot = (points / tickSize) * tickValue;
double rawLots = riskAmount / lossPerLot;
// Round to broker allowed steps
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double cleanLots = MathFloor(rawLots / stepLot) * stepLot;
return MathMax(cleanLots, minLot);
}
//+------------------------------------------------------------------+
//| Execution Wrapper |
//+------------------------------------------------------------------+
void ExecuteTrade(int type, double slPips)
{
if(!IsDrawdownCompliant())
{
Alert("TRADE BLOCKED: Daily Drawdown limit is active.");
return;
}
double lots = CalculateLotSize(slPips);
// Proceed with OrderSend() using the calculated lots...
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
Architectural Notes for Production:
The Flat-Account Trigger: In the cTrader example, notice the foreach loop inside OnTick. If your equity dips below the hard limit while a trade is running, the script acts as a safety net and aggressively flattens all positions to prevent the firm from blowing the account on their backend.
Commission Accounting: Prop firms calculate DD on equity including commissions and swaps. Account.Equity (cTrader) and ACCOUNT_EQUITY (MQL5) factor in floating PnL, but ensure you test how your specific broker feeds swap costs at rollover if you hold overnight.
Server Restarts: If your VPS reboots mid-day, the EA will initialize with the current balance as the start-of-day balance. For production, write the _startOfDayBalance to a local CSV or Global Variable so it persists through terminal crashes.
The Flat-Account Trigger: In the cTrader example, notice the foreach loop inside OnTick. If your equity dips below the hard limit while a trade is running, the script acts as a safety net and aggressively flattens all positions to prevent the firm from blowing the account on their backend.
Commission Accounting: Prop firms calculate DD on equity including commissions and swaps. Account.Equity (cTrader) and ACCOUNT_EQUITY (MQL5) factor in floating PnL, but ensure you test how your specific broker feeds swap costs at rollover if you hold overnight.
Server Restarts: If your VPS reboots mid-day, the EA will initialize with the current balance as the start-of-day balance. For production, write the _startOfDayBalance to a local CSV or Global Variable so it persists through terminal crashes.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
For a high-volume trading environment where uptime is critical, you must persist two variables: the Start of Day Balance and the Day of the Year.
If you only save the balance, a VPS crash that spans across the server's midnight rollover will cause the EA to apply yesterday's balance to today's session.
Here is how you implement this natively in both platforms without relying on slow file I/O operations (like CSVs), which can block the execution thread.
1. MetaTrader 5 (MQL5): Global Variables
MT5 has a built-in Global Variables (GV) table. These variables exist outside the EA, survive terminal restarts, and are stored in the gvariables.dat file automatically. Since you might run this on multiple accounts, append the account number to the GV name so limits don't cross-contaminate.
If you only save the balance, a VPS crash that spans across the server's midnight rollover will cause the EA to apply yesterday's balance to today's session.
Here is how you implement this natively in both platforms without relying on slow file I/O operations (like CSVs), which can block the execution thread.
1. MetaTrader 5 (MQL5): Global Variables
MT5 has a built-in Global Variables (GV) table. These variables exist outside the EA, survive terminal restarts, and are stored in the gvariables.dat file automatically. Since you might run this on multiple accounts, append the account number to the GV name so limits don't cross-contaminate.
Code: Select all
//+------------------------------------------------------------------+
//| State Management Variables |
//+------------------------------------------------------------------+
string gv_balance_name;
string gv_day_name;
double g_startOfDayBalance = 0.0;
int g_currentDay = -1;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Create unique keys for this specific account
long accNum = AccountInfoInteger(ACCOUNT_LOGIN);
gv_balance_name = "RiskMgr_StartBalance_" + IntegerToString(accNum);
gv_day_name = "RiskMgr_Day_" + IntegerToString(accNum);
// Load state from disk if it exists
if(GlobalVariableCheck(gv_balance_name) && GlobalVariableCheck(gv_day_name))
{
g_startOfDayBalance = GlobalVariableGet(gv_balance_name);
g_currentDay = (int)GlobalVariableGet(gv_day_name);
Print("Recovered state from GV. Balance: ", g_startOfDayBalance, " Day: ", g_currentDay);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
MqlDateTime timeStruct;
TimeCurrent(timeStruct);
// Check if we rolled over into a new session
if(timeStruct.day_of_year != g_currentDay)
{
g_startOfDayBalance = AccountInfoDouble(ACCOUNT_BALANCE);
g_currentDay = timeStruct.day_of_year;
// Write to persistent Global Variables
GlobalVariableSet(gv_balance_name, g_startOfDayBalance);
GlobalVariableSet(gv_day_name, g_currentDay);
Print("New Session Anchored & Saved. Balance: ", DoubleToString(g_startOfDayBalance, 2));
}
// Proceed to drawdown checks...
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Scaling rules after payout — keeping challenge habits on funded
2. cTrader (C#): LocalStorage
In cTrader, avoid standard System.IO.File operations inside OnTick or OnStart unless you are wrapping them in async tasks. Instead, use the native LocalStorage API which handles thread-safe persistence in the background.
In cTrader, avoid standard System.IO.File operations inside OnTick or OnStart unless you are wrapping them in async tasks. Instead, use the native LocalStorage API which handles thread-safe persistence in the background.
Code: Select all
using System;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PostPayoutRiskManager : Robot
{
private string _storageKeyBalance;
private string _storageKeyDay;
private double _startOfDayBalance;
private int _currentDay = -1;
protected override void OnStart()
{
// Create account-specific keys
_storageKeyBalance = $"RiskMgr_Balance_{Account.Number}";
_storageKeyDay = $"RiskMgr_Day_{Account.Number}";
// Retrieve saved state (defaults to 0 / -1 if not found)
_startOfDayBalance = LocalStorage.GetObject<double>(_storageKeyBalance);
_currentDay = LocalStorage.GetObject<int>(_storageKeyDay);
if (_startOfDayBalance > 0)
{
Print($"Recovered state: Balance {_startOfDayBalance}, Day {_currentDay}");
}
}
protected override void OnTick()
{
int serverDay = Server.Time.DayOfYear;
// Anchor new session if the day changes (or upon first run)
if (serverDay != _currentDay)
{
_startOfDayBalance = Account.Balance;
_currentDay = serverDay;
// Persist to LocalStorage instantly
LocalStorage.SetObject(_storageKeyBalance, _startOfDayBalance);
LocalStorage.SetObject(_storageKeyDay, _currentDay);
Print($"New Session: Balance Anchored & Saved at {_startOfDayBalance}");
}
// Proceed to drawdown checks...
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.