Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tripolskypetr/pump-anomaly/llms.txt

Use this file to discover all available pages before exploring further.

MetaLedger is a serializable state record that tracks every PumpMatrix.fit() attempt and enforces two invariants against meta-level overfitting — the kind that arises when fit() is called repeatedly inside an automated loop. The problem: DSR penalises the N configurations tried within a single fit(). But if the loop runs fit() 720 times per month and only promotes the model when certified: true, each “certified” run may itself be the lucky outlier among 720 attempts — a winner’s curse at the meta level. A single-fit certificate is blind to the chain it was selected from. MetaLedger closes this gap with two mechanisms:
  1. Cadence guardcanRefit() refuses a new fit() that comes too soon after the last one. Frequent re-fitting is trial multiplication; the guard simply disallows it.
  2. Family-wise correction — when metaLedger is passed to fit(), the DSR’s nTrials becomes effectiveTrials — the sum of inner grid sizes across all recorded fit attempts, not just the current one.

MetaLedgerState

The complete state is a plain, JSON-serializable object. Persist it between ticks (write to disk, a database, or environment state).
interface MetaLedgerState {
  /** ALL fit attempts — certified and uncertified alike */
  attempts: Array<{
    /** Unix timestamp when the fit was started (ms epoch) */
    ts: number;
    /** Number of grid configurations in this fit (inner trials) */
    innerTrials: number;
    /** Whether this fit was certified by its own (naïve, single-fit) criterion */
    certifiedNaive: boolean;
  }>;
}
attempts
FitAttempt[]
Ordered list of all fit attempts. Must include every attempt — logging only successes understates the effective trial count and makes the family-wise correction lie.
attempts[].ts
number
Unix timestamp in milliseconds when the fit was launched.
attempts[].innerTrials
number
Grid size of that fit — the number of configurations evaluated during model selection.
attempts[].certifiedNaive
boolean
Whether model.certification.certified was true for that fit. Stored for audit; does not affect the cadence guard or trial count.

MetaPolicy and DEFAULT_META_POLICY

MetaPolicy is the cadence-policy interface consumed by canRefit. Both the interface and the default constant are exported from the package.
interface MetaPolicy {
  /** Minimum interval between fits (ms). Default: 7 days. */
  minRefitMs: number;
}

const DEFAULT_META_POLICY: MetaPolicy = {
  minRefitMs: 7 * 24 * 3600_000, // one week
};
minRefitMs
number
Minimum milliseconds that must elapse between consecutive fit() calls. The default of 604_800_000 (7 days) ensures each refit incorporates at least one week of new market data rather than re-drawing on the same history.

emptyLedger

emptyLedger(): MetaLedgerState
Returns a fresh MetaLedgerState with an empty attempts array. Call this once when initialising the loop state; then pass the ledger forward on every tick.
import { emptyLedger } from "pump-anomaly";

let ledger = emptyLedger();
// { attempts: [] }
returns
MetaLedgerState
{ attempts: [] } — ready to be used as the initial loop state.

canRefit

canRefit(
  ledger: MetaLedgerState,
  now: number,
  policy?: MetaPolicy,
): { allowed: boolean; reason: string; nextAllowedTs: number }
Checks whether a new fit() is permitted under the cadence policy. If the ledger is empty (first ever fit), it is always allowed. Otherwise, the function checks whether now ≥ lastFitTs + minRefitMs. The default minRefitMs is 7 days (7 × 24 × 3600 × 1000 ms). This reflects the idea that a week of new market data is the minimum meaningful increment for retraining a pump-detection model; anything shorter is re-running the same data under a different random draw, which is just trial multiplication.
ledger
MetaLedgerState
required
Current ledger state.
now
number
required
Current Unix timestamp in milliseconds. Pass Date.now() in production.
policy
MetaPolicy
Cadence policy. Omit to use DEFAULT_META_POLICY (7-day minimum interval). Pass a custom MetaPolicy to override minRefitMs.
policy.minRefitMs
number
Minimum milliseconds between fits. Default: 604_800_000 (7 days).
allowed
boolean
true if a new fit is permitted right now.
reason
string
Human-readable explanation. Examples:
  • "первый fit" (first fit ever)
  • "интервал выдержан" (interval satisfied)
  • "слишком частый refit: до следующего разрешённого 3.5ч. Частое переобучение размножает испытания (мета-winner's-curse)." (too soon)
nextAllowedTs
number
Unix timestamp in milliseconds when the next fit will be permitted. Equal to lastFitTs + minRefitMs, or now on the first fit.
import { canRefit } from "pump-anomaly";

const gate = canRefit(ledger, Date.now());
if (!gate.allowed) {
  console.log(gate.reason);
  console.log("Next allowed:", new Date(gate.nextAllowedTs).toISOString());
  return;
}
// proceed to fit()

recordAttempt

recordAttempt(
  ledger: MetaLedgerState,
  attempt: {
    ts: number;
    innerTrials: number;
    certifiedNaive: boolean;
  },
): MetaLedgerState
Returns a new MetaLedgerState with the given attempt appended. The original ledger is not mutated (the function is pure). You must call recordAttempt for every fit attempt — certified or not. Recording only the successful fits understates the effective number of trials. The family-wise DSR correction only works because the denominator includes all attempts.
ledger
MetaLedgerState
required
Current ledger state.
attempt.ts
number
required
Unix timestamp of this fit (ms).
attempt.innerTrials
number
required
Grid size — available as model.innerTrials after fit() returns.
attempt.certifiedNaive
boolean
required
Whether this fit was individually certified — model.certification.certified.
returns
MetaLedgerState
New ledger with the attempt appended. Assign this back to your ledger variable.

effectiveTrials

effectiveTrials(ledger: MetaLedgerState, currentInnerTrials: number): number
Returns the total effective trial count for the family-wise DSR correction:
effectiveTrials = Σ attempt.innerTrials  +  currentInnerTrials
This is the honest denominator for deflatedSharpe. If the loop has run fit() three times with grids of 500, 480, and 520 configurations, and the current fit used 500 configs, the effective trial count is 500 + 480 + 520 + 500 = 2000 — not 500. When you pass metaLedger to fit(), the library calls effectiveTrials internally and uses it as nTrials in deflatedSharpe. The result is exposed on the model as model.effectiveTrials.
ledger
MetaLedgerState
required
Current ledger (before the current fit is recorded).
currentInnerTrials
number
required
Grid size of the current fit (model.innerTrials).
returns
number
Total effective trials ≥ 1. Always at least currentInnerTrials.

fitAttemptCount

fitAttemptCount(ledger: MetaLedgerState): number
Returns the number of fit attempts recorded in the ledger — ledger.attempts.length. Useful for reporting and for manual Bonferroni-style threshold adjustment.
ledger
MetaLedgerState
required
Current ledger state.
returns
number
Total number of recorded fit attempts.

Full Usage Pattern

The complete loop wires all four functions together. The ledger is the only mutable state; everything else is a pure transformation.
import {
  emptyLedger,
  recordAttempt,
  canRefit,
  effectiveTrials,
} from "pump-anomaly";
import { PumpMatrix } from "pump-anomaly";

// Initialize once; persist across ticks (write to disk / DB between runs)
let ledger = emptyLedger();

async function tick(history, getCandles) {
  // 1. Cadence gate — refuse too-frequent refits
  const gate = canRefit(ledger, Date.now());
  if (!gate.allowed) {
    console.log(gate.reason, "next allowed:", new Date(gate.nextAllowedTs));
    return;
  }

  // 2. Train — pass the ledger so DSR uses effectiveTrials
  const model = await PumpMatrix.fit(history, getCandles, { metaLedger: ledger });

  // 3. Log EVERY attempt — certified or not
  ledger = recordAttempt(ledger, {
    ts: Date.now(),
    innerTrials: model.innerTrials,
    certifiedNaive: model.certification.certified,
  });

  // 4. Inspect meta-level counters
  console.log(
    "effectiveTrials:", model.effectiveTrials,
    "fitAttempts:", model.fitAttempts,
  );

  // 5. Only deploy a certified model
  if (model.certification.certified) {
    // safe to use for live trading
    const trades = await model.plan(latestSignals, getCandles);
    for (const t of trades) {
      openPosition(t.symbol, t.direction, t.exit);
    }
  } else {
    console.log("Not certified:", model.certification.reasons);
  }
}
Passing metaLedger to fit() is optional but strongly recommended for any automated training loop. Without it, the DSR only penalises configurations within the current fit’s grid — it cannot see that this fit is itself one of many attempts from which you are selecting the certified outcome. The family-wise correction is only applied when the ledger is provided.

Build docs developers (and LLMs) love