Skip to content

Prop Trading API

The Prop Trading manager API is used by BackOffice to configure prop challenge products.

This API belongs to the TCP manager layer. Client-facing challenge browsing and purchase endpoints are documented in the HTTP Client API section.

Lifecycle

Current implementation covers the configuration layer and the client purchase activation flow:

  1. BackOffice creates a program aggregate with settings and steps.
  2. BackOffice opens the full program card with MngGetPropProgram.
  3. BackOffice updates settings and steps with one MngUpdatePropProgram request.
  4. BackOffice can activate/disable a program through MngUpdatePropProgram.status.
  5. BackOffice can delete a program and all linked prop records through MngDeletePropProgram.
  6. BackOffice can view current challenges through MngGetPropChallangesByFilter.
  7. BackOffice can open challenge runtime details through MngGetPropChallenge, MngGetPropChallengeMetrics, and MngGetPropChallengeBreaches.
  8. BackOffice can view and manage purchase lifecycle metadata through MngGetPropPurchasesByFilter, MngGetPropPurchase, MngUpdatePropPurchase, and MngDeletePropPurchase.
  9. Client requests available active programs.
  10. Client starts a purchase with BuyPropChallenge.
  11. Server creates a prop_purchase, enqueues the payer fee withdrawal, opens the first phase account in steps[0].account_group, enqueues the initial balance from that group's GroupRecord.default_deposit, and creates an active prop_challenge.
  12. Server creates an active prop_challenge_phases row for the current phase.
  13. PropManager evaluates active phases in its own loop by reading margin data in batches through AccountManager::GetMarginsByLoginsList.

Funded support is modelled as a phase type. A program can contain at most one funded phase, and it must be the last phase. The funded phase must use a REAL trading group.

The Prop evaluator does not run inside the trading mainLoop. It checks active phase accounts from the PropManager cache, writes throttled metric snapshots, creates rule breaches, and moves a phase/challenge to failed or passed state.

Heavy side effects are executed by a separate PropManager worker queue. The evaluator only enqueues jobs. The worker can set failed accounts read-only, create the next phase account, enqueue the phase initial balance, update current_phase_index/account_login, and execute funded profit payout.

PropManager is cache-first. SQLite is used for startup load and persistence, while runtime/API read paths use in-memory indexes for purchases, challenges, challenge phases, metrics, breaches and daily snapshots. Metric snapshots and rule breaches are kept in memory newest-first and capped to the latest 1000 rows per challenge; SQLite keeps the full history.

If the passed phase is the last phase, the challenge becomes passed. If a next phase exists, the current runtime phase becomes passed and the worker creates the next phase account.

Status Values

Program Status

Value Name Description
0 active Available for use
1 disabled Not available for new purchases
2 archived Hidden/legacy record

MngUpdatePropProgram can activate a program with status = 0 or disable it with status = 1.

Purchase Status

Value Name
0 pending
1 paid
2 account_created
3 active
4 failed
5 refunded

Challenge Status

Value Name
0 pending
1 active
2 passed
3 failed
4 cancelled

Challenge Phase Status

Value Name
0 pending
1 active
2 passed
3 failed
4 cancelled

Program Object

Field Type Description
id int Program id
brand string Brand namespace
name string Program name shown to BackOffice/client
description string Program description
price double Challenge purchase price
price_currency string Purchase currency
profit_split double Trader profit share derived from the funded phase. 0.8 means 80%. Returns 0.0 when the program has no funded phase
status int Program status
sort_index int UI ordering value
created_time int Unix timestamp
updated_time int Unix timestamp

Aggregate Save Model

MngCreatePropProgram requires a nested steps array. MngUpdatePropProgram can replace steps by sending steps. Each step contains phase settings, rule values and the phase account_group. demo_group is deprecated and is not used by new prop flows.

{
  "steps": [
    {
      "phase_index": 1,
      "phase_type": 0,
      "name": "Evaluation",
      "account_group": "PROP_DEMO_USD",
      "initial_balance": 100000,
      "duration_days": 30,
      "max_daily_loss_pct": 5,
      "max_total_loss_pct": 10,
      "max_daily_profit_pct": 0,
      "profit_target_pct": 8,
      "profit_split": 0,
      "min_trading_days": 5,
      "max_trading_days": 30,
      "max_positions": 10
    },
    {
      "phase_index": 2,
      "phase_type": 1,
      "name": "Funded",
      "account_group": "PROP_REAL_USD",
      "initial_balance": 100000,
      "duration_days": 30,
      "max_daily_loss_pct": 5,
      "max_total_loss_pct": 10,
      "max_daily_profit_pct": 5,
      "profit_target_pct": 0,
      "profit_split": 0.8,
      "min_trading_days": 0,
      "max_trading_days": 30,
      "max_positions": 10
    }
  ]
}

On update, if steps is sent, the server replaces nested program steps as one aggregate.

Delete Flow

MngDeletePropProgram removes the program and all linked prop-domain records:

  • program steps/phases
  • purchases
  • challenges
  • challenge phase runtime rows
  • daily snapshots
  • rule breaches
  • metric snapshots
  • the program row

The delete operation is transactional and writes the deleted counters to the server log.

Phase Object

Field Type Description
id int Phase id
program_id int Parent program id
phase_index int Phase order starting from 1
phase_type int 0 evaluation, 1 funded
name string Phase name
account_group string Trading group used for the phase account. Funded phases must use a REAL group
initial_balance double Computed from account_group -> GroupRecord.default_deposit
duration_days int Phase duration, 0 means not configured
max_daily_loss_pct double Maximum daily loss percent
max_total_loss_pct double Maximum total loss percent
max_daily_profit_pct double Maximum daily profit percent, mostly used for funded phases
profit_target_pct double Profit target percent
profit_split double Trader profit share for funded phase. 0.8 means 80%. Must be 0 for non-funded phases
min_trading_days int Minimum trading days
max_trading_days int Maximum trading days, 0 means not configured
max_positions int Maximum open positions, 0 means not configured
created_time int Unix timestamp
updated_time int Unix timestamp

Funded Phase Rules

  • phase_type = 1 marks a funded phase.
  • A program can have only one funded phase.
  • The funded phase must be the last phase by phase_index.
  • The funded phase account_group must point to a REAL group.
  • Non-funded phases must use DEMO groups in the current implementation.
  • profit_split is stored on the funded phase and exposed on the program object as a computed field.

Runtime Evaluation

When a challenge is activated, the server creates a runtime phase row with the starting balance/equity snapshot.

The evaluator currently checks:

  • max_total_loss_pct
  • max_daily_loss_pct
  • max_daily_profit_pct
  • duration_days
  • profit_target_pct
  • min_trading_days
  • max_trading_days
  • max_positions

Metrics are written to prop_metric_snapshots at most once per minute per challenge, and immediately on pass/fail events. Rule violations are written to prop_rule_breaches.

On breach the worker sets the failed phase account to read-only and emits prop.challenge.failed. On phase advance it emits prop.challenge.phase_changed. On final pass it emits prop.challenge.passed.

Daily loss/profit use prop_daily_snapshots.daily_start_equity as the daily boundary basis. The first evaluator pass in a local calendar day creates the daily snapshot, then updates current balance/equity and min/max equity.

Current limitation: trading days are counted from daily snapshots, not strictly from trade activity.

Runtime Detail Commands

  • MngGetPropChallenge returns challenge, purchase, program, runtime phases, current phase, latest metric and latest breach. Each phase includes latest_metric and calculated progress.
  • MngGetPropChallengeMetrics returns prop_metric_snapshots rows, newest first.
  • MngGetPropChallengeBreaches returns prop_rule_breaches rows, newest first.

Purchase Commands

  • MngGetPropPurchasesByFilter returns purchases in the BackOffice table format.
  • MngGetPropPurchase returns one purchase card with linked program and challenges.
  • MngUpdatePropPurchase updates only lifecycle/meta fields.
  • MngDeletePropPurchase deletes an unlinked purchase, or a linked purchase only when it is already failed or refunded.