Don’t forget to share it with your network!
Ajaysingh Narayansingh Rajpurohit
Sr Developer, Softices
MetaTrader 5 Development
15 May, 2026
Ajaysingh Narayansingh Rajpurohit
Sr Developer, Softices
Most prop trading firms hit a wall around 200–300 active challenges. Not because their traders aren't performing but because the infrastructure holding everything together starts breaking at scale. Manual account resets, spreadsheet-tracked drawdowns, and copy-pasted challenge rules were never meant to run a real business.
MetaTrader 5 is an exceptional trading platform. It is not a prop firm operating system. That distinction matters, because building your firm on the assumption that MT5 handles both is exactly where the operational debt starts piling up.
This article explains how to build a custom backend on top of MT5 using the Manager API, what the architecture looks like, how each layer works, and what you need to get it right.
MT5 handles order execution, position management, and market data with institutional precision including tools like Expert Advisors for automated trade execution. What it does not handle is the business logic that wraps around those trades.
A functioning prop firm needs:
None of this is built into MT5 as a complete system. The trading layer is there. The operational layer is not. That layer has to be built, and the MT5 Manager API is the interface that connects your backend to the platform.
MT5 offers several integration points, each serving a different purpose:
API |
Primary Use |
|---|---|
| Gateway API | Market data distribution |
| Trade Server API | Order execution and routing |
| Manager API | Server-side account and group management |
For prop firm infrastructure, the Manager API is the correct tool. It operates at the administration layer of the MT5 server, giving your backend the ability to act on accounts and trading data rather than just observe them.
With the Manager API, your backend can:
Think of it as the control plane for your MT5 server. Your backend sends instructions; MT5 executes them.
Before writing any backend code, make sure these are in place before development starts.
Standard trading accounts will not work. You need manager-level credentials from a licensed broker or MT5 server provider. Without this, none of the Manager API calls are available to you.
The Manager API ships with official SDKs for C++ and C#. Most teams choose C# because it integrates more cleanly with REST APIs, background job systems, and modern backend frameworks.
Plan for multiple stores from the start:
This system has direct control over trading accounts. Security is not optional:
Once your service establishes a connection to the MT5 server, you have access to operations like:
UserRecordNew (userRecord) → create a new trading account
UserRecordUpdate (userId, updatedRecord) → update account settings or move phases (e.g., from
Challenge to Funded)
TradeRequestSend (closeRequest) → close or manage trades
PositionGetTicket (accountId) → fetch all open positions for an account
HistoryOrderSelect (accountId, fromDate, toDate) → pull historical trade records for payout calculation
One thing to understand clearly: the Manager API does not push real-time updates. Your backend must poll the MT5 server at regular intervals, typically every 10 to 30 seconds depending on your risk tolerance and process the results in your own system.
This polling architecture shapes everything about how you build the backend.
We build the backend infrastructure that automates your challenge system, risk engine, and payouts end to end.
A production prop firm backend has four main layers:
A lightweight, dedicated service responsible for:
maintaining a stable connection to the Manager API
polling account and trade data on schedule
pushing results into Redis
This service should be isolated from business logic. Its only job is data collection and connection management.
public class MT5ConnectorService
{
private readonly IMT5ManagerAPI _manager;
private readonly IRedisCache _cache;
public async Task PollAccountData(int accountId)
{
var positions = await _manager.PositionGetTicket(accountId);
var equity = CalculateEquity(positions);
await _cache.SetAsync($"account:{accountId}:equity", equity);
await _cache.SetAsync($"account:{accountId}:positions", positions);
}
}
This is the main logic layer.
It reads from Redis for real-time state and writes final records to PostgreSQL.
Two separate interfaces serve different users:
The challenge system is the core product logic of your firm. Every other component supports it.
When a trader purchases a challenge, your backend:
UserRecordNew to create an MT5 account with the correct
parameters
challenge_phase1_100k)
public async Task<ChallengeAccount> CreateChallenge(int userId, ChallengeConfig config)
{
var mt5Account = await _manager.UserRecordNew(new UserRecord
{
Group = config.GroupName,
Leverage = config.Leverage,
Balance = config.AccountSize
});
var challenge = new ChallengeAccount
{
UserId = userId,
MT5Login = mt5Account.Login,
StartingBalance = config.AccountSize,
ProfitTarget = config.AccountSize * config.ProfitTargetPct,
MaxDrawdownLimit = config.AccountSize * config.MaxDrawdownPct,
DailyLossLimit = config.AccountSize * config.DailyLossPct,
Phase = 1,
Status = ChallengeStatus.Active
};
await _db.ChallengeAccounts.AddAsync(challenge);
return challenge;
}
A background job runs on a schedule, every 15 to 30 seconds for most firms and evaluates every active account against its rules.
public async Task EvaluateAccount(ChallengeAccount challenge)
{
var currentEquity = await _cache.GetAsync<decimal>($"account:{challenge.MT5Login}:equity");
var dailyLow = await _cache.GetAsync<decimal>($"account:{challenge.MT5Login}:daily_low");
var drawdown = challenge.StartingBalance - currentEquity;
var dailyLoss = challenge.DailyOpeningBalance - dailyLow;
var profit = currentEquity - challenge.StartingBalance;
// Check failure conditions first
if (drawdown >= challenge.MaxDrawdownLimit || dailyLoss >= challenge.DailyLossLimit)
{
await FailAccount(challenge);
return;
}
// Check success conditions
if (profit >= challenge.ProfitTarget && challenge.Phase < challenge.TotalPhases)
{
await AdvancePhase(challenge);
}
else if (profit >= challenge.ProfitTarget && challenge.Phase == challenge.TotalPhases)
{
await TransitionToFunded(challenge);
}
}
When an account passes a phase:
UserRecordUpdate to move the account to the next group
on the MT5 server
When an account fails:
TradeRequestSendRisk management is where the backend earns its keep. Two layers handle this: pre-trade validation and live monitoring.
Before a trade is allowed to execute, your system validates:
After trades are open, the connector service tracks:
If equity breaches a threshold, the backend calls
TradeRequestSend to close all open positions immediately and
flags the account for review.
public async Task CheckLiveRisk(int mt5Login)
{
var equity = await _cache.GetAsync<decimal>($"account:{mt5Login}:equity");
var challenge = await _db.GetActiveChallengeByLogin(mt5Login);
if (equity <= challenge.StartingBalance - challenge.MaxDrawdownLimit)
{
await _manager.CloseAllPositions(mt5Login);
await FailAccount(challenge, FailureReason.MaxDrawdownBreached);
}
}
Redis is the right tool here because you need sub-second reads on current equity state, not round-trips to PostgreSQL.
Once a trader is in a funded account, profit splits are calculated from their closed trade history.
HistoryOrderSelectpublic async Task<PayoutRecord> CalculatePayout(int mt5Login, DateTime periodStart, DateTime periodEnd)
{
var trades = await _manager.HistoryOrderSelect(mt5Login, periodStart, periodEnd);
var grossProfit = trades
.Where(t => t.State == OrderState.Filled)
.Sum(t => t.Profit);
var traderShare = grossProfit * TRADER_PROFIT_SPLIT; // e.g., 0.80
var firmShare = grossProfit * (1 - TRADER_PROFIT_SPLIT);
return new PayoutRecord
{
MT5Login = mt5Login,
GrossProfit = grossProfit,
TraderAmount = traderShare,
FirmAmount = firmShare,
Period = (periodStart, periodEnd),
Status = PayoutStatus.PendingApproval
};
}
Whether payouts are triggered automatically or require manual approval is a business decision. Either way, every record should be fully traceable back to the specific trades that generated it.
Here is how data moves through the system end to end:
Trader places trade in MT5 terminal ↓ MT5 Connector polls Manager API (every 15–30s) ↓ Raw data pushed to Redis (equity, positions, drawdown state) ↓ Processing service reads Redis → evaluates challenge rules ↓ State changes written to PostgreSQL (phase transitions, failures) ↓ Metrics written to InfluxDB (equity curve snapshots) ↓ Dashboard reads PostgreSQL + InfluxDB → displays to trader/admin
This cycle runs continuously. The separation between Redis (real-time) and PostgreSQL (persistent) is intentional. It keeps the rule evaluation fast without hammering your primary database.
The Manager API connection will drop occasionally.
Polling per account stops working above a few hundred accounts.
Always calculate drawdown from the starting balance stored in your database at account creation. Do not rely on MT5's internal balance adjustments. They can differ due to swaps, credits, and corrections.
All MT5 server groups (challenge phases, funded, failed, reset) must exist on the server before launch. Create and test them in a staging environment first. Trying to assign an account to a non-existent group will throw an error that silently breaks your onboarding flow.
A few things matter significantly when you go live:
The base system gives you full operational control. Extensions that firms commonly add next:
A prop firm backend is not a trading system. It is a rules and operations layer that sits on top of MT5 and manages how traders move through challenges, risk limits, and payouts.
The Manager API gives you access to the MT5 server's control layer. Everything around it including the challenge logic, the risk engine, the payout system, the dashboards has to be designed and built separately.
Done well, this architecture gives you complete control over your trading program: consistent rule enforcement, automated operations, and a system that scales without adding headcount.
If you'd prefer not to build this from scratch, Softices builds custom MT5 backends and Manager API integrations for prop firms, brokers, and fintech platforms.