@luxalgo/prop-firm-sim-core
Seedable, browser-safe Monte Carlo engine for prop-firm challenge
simulation: pass probability, expected attempts, expected total cost, EV,
and optimal risk sizing - from a trader profile and a firm's exact
ruleset, with every assumption visible.
Pure math, zero dependencies on I/O: no network, no filesystem, no
telemetry, no keys. Runs identically in Node and the browser (web workers
included). Same seed + same inputs ⇒ byte-identical results on any platform.
Part of LuxAlgo/prop-firm-sim
(MIT) - the repo README covers the rule semantics in depth, and the same
engine powers the CLI,
the MCP server,
and the hosted simulator.
Install
npm install @luxalgo/prop-firm-sim-core
Quick start
import { simulate } from "@luxalgo/prop-firm-sim-core";
import { adaptFirm } from "@luxalgo/prop-firm-sim-core/directory";
const { propfirms } = (await (await fetch("https://app.luxalgo.com/api/propfirms/list")).json()).data;
const challenge = adaptFirm(propfirms.find((f) => f.propfirmId === "topstep"))[0];
const result = simulate(
challenge.spec,
{
kind: "parametric",
winRate: 0.45,
avgWinR: 1.4,
avgLossR: 1,
tradesPerDay: 4,
tradesPerDayModel: "poisson",
risk: { mode: "percent-of-initial", value: 1 },
},
{ seed: 42, paths: 10_000 },
);
console.log(result.perAttempt.passProbability);
console.log(result.perAttempt.failureBreakdown);
console.log(result.ev.evTotal);
console.log(result.assumptions.flags);
console.log(challenge.provenance, challenge.inferredFields);
…or an inline spec for any ruleset:
const custom = {
challengeId: "my-100k",
name: "My 100K 2-Step",
accountSize: 100_000,
steps: [{ profitTargetPct: 8 }, { profitTargetPct: 5 }],
dailyLoss: { pct: 5 },
maxLoss: { pct: 10, mode: "static-initial" },
fees: { price: 500, refundableOnPass: true },
funded: { profitSplitPct: 80, payoutFrequency: "biweekly" },
};
What it simulates
- All four "trailing drawdown" semantics -
static-initial,
trailing-realized-eod, trailing-intraday-unrealized,
trailing-locks-at-initial, plus composable locks (locksAtInitial,
lockOffsetAmount). The gap between them is up to ~2x in pass
probability at the same limit size.
- Daily-loss mechanics - anchor basis (prior-day balance vs equity),
limit basis (fixed allowance vs recomputed), open-P&L inclusion,
intraday vs end-of-day evaluation.
- Consistency rules - simulated with a rational stop rule, not
footnoted: one outsized day raises your effective target.
- The funded stage - payout gating (winning-day minimums, caps,
buffers, windowed consistency), profit splits, blowup risk, and a
maximum-withdrawal model where balances and loss floors carry across
payouts.
- Your real trades - a stationary block bootstrap resamples your actual
R-multiple series with streaks preserved (streaks are what breach these
rules; i.i.d. win-rate math flatters you).
- Stagnation - every result reports the longest stretch of days without
a new equity high per attempt (
perAttempt.stagnationDays); lower risk
survives more and stagnates longer.
- Trade-log context tools -
parseTradeLog (timestamped CSV/TSV),
filterTradesAroundNews (recurring high-impact calendar, configurable
pre/post minutes, impact and currency filters, disclosed approximation),
and mergeTradeLogs/analyzeOverlap (combine up to five strategy
histories and measure the same-direction position overlap a prop-firm
reviewer would see, with disclosed heuristic audit-risk bands).
Also exported: optimalRisk (pass-optimal vs EV-optimal risk sweep -
they usually differ), compare (same trader across many rulesets),
parseRSeries, and the RNG/bootstrap primitives.
Honesty contract
Every result carries assumptions: the fully-resolved spec/profile/options
the engine actually ran, flags for every rule it did not simulate, and a
disclaimer. Results are Monte Carlo distributions under stated assumptions -
never promises. Adapted directory challenges carry their provenance
(directory vs directory+inferred with the inferred fields named), pass
source citations through when the directory serves them, and are refused
outright when their loss rules are ambiguous. Firms change rules; the firm's
own page is always authoritative.
License
MIT © LuxAlgo