wfaProfessional is the core engine module that builds Professional WFA artifacts from normalized walk-forward periods and an optional performance transfer (equity curve transfer).
It computes 7 blocks plus an institutional grade and a textual recommendation:
equityCurveAnalysiswfeAdvancedparameterStabilityregimeAnalysismonteCarloValidation(bootstrap over window OOS returns today; see §5 - not path-level Monte Carlo yet)stressTestinstitutionalGrade(grade + recommendation)
This module is intended for use in server-side or batch pipelines (not in minimal analyze() CLI demos). It is intended for institutional and professional interpretation. It does not expose ad-hoc tuning knobs; the output is derived from the provided periods (and optionally from transferred equity curve points).
The engine-core exports the following functions from wfaProfessional:
validateAndNormalizeWfaInput(wfa)- normalizes input into numeric periods and optionally extracts/sorts curve points.buildProfessionalWfa(validationResult)- builds the 7 blocks from normalized periods.runProfessionalWfa(wfa)- combines validation + build; returnsnullwhen input cannot produce a professional report.
If runProfessionalWfa(...) (or buildProfessionalWfa(...)) cannot validate the input (for example, not enough periods), it returns null.
wfaProfessional expects:
- A
periodsarray (orwindowsalias) where each period provides:optimizationReturnandvalidationReturn(expected to be decimal returns after contract normalization).- Optional
parametersthat can be numeric (used for parameter stability).
- Optional
performanceTransferwhich can contain curve points viaperformanceTransfer.windows[].oosEquityCurve(orequityCurveorcurvealiases).
When curve points are missing or too short, curve-based blocks may become unavailable (for example equityCurveAnalysis).
Represents analysis of the out-of-sample equity curve (transferred curve or approximated curve when transfers are not available enough).
Key fields:
available: booleanchunkStats?: Array<{ return: number; volatility: number; maxDrawdown: number }>trendConsistency?: "HIGH" | "MEDIUM" | "LOW"overallTrend?: "UP" | "FLAT" | "DOWN"volatilityProgression?: number[]verdict?: "STRONG" | "ACCEPTABLE" | "WEAK"
If the curve is too short for reliable chunking, equityCurveAnalysis becomes unavailable (available: false).
Rank-based walk-forward efficiency plus a one-sided permutation null for OOS shuffles (WFE v2; same shape as public WFAAnalysisOutput.wfe).
Key fields:
rankWfe: number- mean over windows of (OOS average rank / IS average rank), each window using independent 1-based tie-aware ranks on IS and OOS series.permutationPValue: number- one-sided p: fraction ofpermutationNrandom OOS shuffles withrankWfe>= observed (seeded RNG per iteration).permutationN: number- permutation count used (typically fromAnalyzeConfig.permutationN, default 1000, bounds 100..10000).windowCount: numberseed: number- seed wired into permutation draws for reproducibility.compositeScore: number- heuristic 0..100 fromrankWfe, with an extra cap when mean IS > 0 and mean OOS < 0.verdict: "ROBUST" | "ACCEPTABLE" | "WEAK" | "FAIL"- heuristic fromrankWfeand the mean IS / mean OOS guard above.
buildProfessionalWfa / runProfessionalWfa accept optional permutationN in the options object alongside seed.
Drift-based parameter stability across periods.
Key fields:
available: booleanparameterDrift?: Record<string, { mean: number; std: number; driftPct: number; stability: "STABLE" | "ADAPTIVE" | "FRAGILE" }>fragileParameters?: string[]overallStability?: "ROBUST" | "ACCEPTABLE" | "FRAGILE"stabilityScore?: number | null
If there are no numeric parameters across the input periods, parameterStability becomes unavailable (parameterStability.available is false and the block is omitted by runProfessionalWfa).
Detects regime shifts and outlier periods using z-scores on validation (OOS) returns.
Key fields:
regimeChanges: Array<{ windowIndex: number; periodNumber: number; value: number; zScore: number; reason: string }>hasOutliers: booleandistributionShape?: "NORMAL" | "SKEWED_RIGHT" | "SKEWED_LEFT" | "HEAVY_TAILS"skewness?: numberkurtosis?: numberverdict?: "STABLE" | "REGIME_SHIFT" | "OUTLIER_DETECTED"
Name vs implementation: The field is called monteCarloValidation for API stability. Current behavior is bootstrap, not a full Monte Carlo simulation over equity paths or trade sequences.
What it does today: The engine takes one validation (OOS) return per walk-forward window (validationReturn). It resamples those scalars with replacement over many iterations (default 1000, clamped to [100, 50_000]; override via AnalyzeConfig.monteCarloBootstrapN on precomputed WFA / buildProfessionalWfa / runProfessionalWfa option bootstrapN), builds the empirical distribution of the mean OOS return across resamples, then derives 68% and 95% intervals with Hyndman–Fan type 7 (percentileType7, same family as path Monte Carlo), probabilityPositive (share of bootstrap means above zero), and a verdict from the bootstrap distribution only.
Verdict rules (aligned with implementation): CONFIDENT if probabilityPositive >= 0.75 and the 95% CI does not straddle zero (ci95Low > 0 or ci95High < 0). PROBABLE if probabilityPositive >= 0.6. UNCERTAIN if probabilityPositive >= 0.5. Otherwise DOUBTFUL.
PRNG: Always Mulberry32 with seed from options when finite; otherwise the same default seed as path MC (PATH_MONTE_CARLO_DEFAULT_SEED in pathMonteCarloConstants.ts). No Math.random fallback.
What it does not do: No path-dependent simulation (no synthetic full equity curves drawn step-by-step, no shock model over returns beyond window resampling, no strategy-path Monte Carlo).
monteCarloMode / enablePathMc (optional): In addition to window bootstrap above, the professional pipeline may emit method: "path_mc_v1" (path simulation from stored equity curves) or method: "unavailable" with a reasonCode, depending on mode, enablePathMc, and data eligibility. See MONTE_CARLO_PATH.md and wfaProfessional.ts / wfaProfessional.test.ts for selection rules. When path MC cannot run, institutional grade aggregation still needs a bounded MC signal: the engine applies a neutral Monte Carlo contribution and records mc_unavailable_neutral_score_50 plus mc_unavailable_reason:* entries in professionalMeta.approximationsUsed.
Key fields:
actualMeanReturn: numberconfidenceInterval95: [number, number]confidenceInterval68: [number, number]probabilityPositive: numberverdict: "CONFIDENT" | "PROBABLE" | "UNCERTAIN" | "DOUBTFUL"
Worst-case analysis and degradation/recovery signals.
Key fields:
worstCaseReturn: numberworstCaseWindow: numberworstCaseDD: number | nullworstCaseDDIsEstimate?: booleanvolatilitySpike?: { degradationPct: number; impact: "Minimal" | "Moderate" | "Significant" }recoveryCapability?: "HIGH" | "MODERATE" | "LOW" | "N/A"verdict?: "RESILIENT" | "ACCEPTABLE" | "FRAGILE"
Curve-based parts (worst-case drawdown and recovery capability) can become estimates or be unavailable depending on curve availability.
Converts block verdicts into a single grade and a human-readable recommendation.
Key fields:
grade:"AAA - INSTITUTIONAL GRADE""AA - PROFESSIONAL""A - ACCEPTABLE""BBB - RESEARCH ONLY"
recommendation: stringinstitutionalGradeOverrideReason?: string- human-readable mirror of structured overridereason(for simple UI).institutionalGradeOverride?: { code, reason, threshold, actualPValue?, actualFailureRate? }- machine-readable (FORMULA_VERSION2.2.0+). Codes:WEAK_STATISTICAL_SIGNIFICANCE- AA/AAA would apply butwfeAdvanced.permutationPValue >= WFE_PERMUTATION_P_WEAK_THRESHOLD(0.10); grade capped to A - ACCEPTABLE.FAIL_VERDICT_HIGH_FAILURE_RATE- WFA verdict FAIL and failed-window rate > 30%; grade capped to BBB - RESEARCH ONLY.
Along with professional, runProfessionalWfa returns professionalMeta:
engineFormulaVersion: string- aligned with packageFORMULA_VERSION(e.g. 2.2.0).version: stringinputsSummary:periodCount: numberhasPerformanceTransfer: booleanhasValidationMaxDD: booleancurvePointCount?: number
guardsTriggered: string[]approximationsUsed: string[]
Use guardsTriggered and approximationsUsed to understand when a block is computed via approximations or when some parts are skipped due to input limitations.
import { runProfessionalWfa } from "@kiploks/engine-core";
const professionalOut = runProfessionalWfa({
periods: [
{ optimizationReturn: 0.1, validationReturn: 0.05, parameters: { p: 1 } },
{ optimizationReturn: 0.12, validationReturn: 0.07, parameters: { p: 2 } },
],
// performanceTransfer is optional
});
if (!professionalOut) {
throw new Error("Professional WFA: insufficient input");
}
console.log(professionalOut.professional.institutionalGrade?.grade);