instrument · method · source · @lotkarun
$LOTKA contract (Solana): TBA

predator-prey market tracker · solana x wall street

lotka

A browser instrument for watching one market eat another. It takes the one-minute motion of a Solana meme token and a legacy equity, normalises both, then lets a small Lotka-Volterra system translate the difference into predation pressure.

market cap
TBA
holders
Sol crypto momentum
112.00
crypto price:
NVDA equity momentum
108.00
equity price:
live · 240-minute window · public candles · pressure = 59.48%· generated

top: the crypto predator and the equity prey, drawn as normalised momentum. the equity trace is delayed by five samples so the chase is visible. bottom: the pressure field produced by the interaction term. the page reads public one-minute candles through a local Next.js route and recomputes the same series in the browser.

01 / 06

What this is.

Most meme coins invent a story and ask the market to pretend it is real. Lotka does the opposite. The story is the measurement. A Solana asset and a Wall Street asset are treated as two populations sharing the same liquidity environment. One is prey. One is predator. Every minute the page asks which population is expanding, which one is being compressed, and how violent the interaction has become.

02 / 06

What the equation says.

Lotka and Volterra wrote the same predator-prey equation from opposite directions, one through chemistry and one through fish markets. In continuous form it describes two populations that rise and fall because each is the condition for the other. Here the populations are not animals. They are momentum fields: x is legacy-market motion, y is Solana-market motion. The browser advances them one discrete step at a time.

dx = alpha x - beta xy
dy = delta xy - gamma y
pressure = sigmoid(y - x + xy)
03 / 06

How the instrument runs.

The page keeps a rolling window of 240 one-minute observations. It converts each side's price change and volume flow into a dimensionless momentum score, applies a discrete interaction term, and maps the result through a sigmoid into a number between 0 and 100. That number is predation pressure. It is not an oracle, a trading signal, or a promise. It is a public compression of the current chase.

04 / 06

Why the line never sleeps.

Crypto trades through weekends and holidays. Equities do not. A dead equity line would make the instrument useless exactly when Solana is most awake. During closed-market hours the equity side is replaced by a small random walk around its last known state, standing in for futures, dark liquidity, and the psychological price people keep carrying after the exchange shuts.

05 / 06

What does not exist.

No private database. No team server. No secret feed. No admin panel deciding which side is winning. The useful version of this page reads public data, computes the model locally, and displays the result. The token is the cultural handle for the measurement, not the source of the measurement.

the source · open-source kernel

The browser program, reproduced verbatim

A zero-backend market instrument. Maintains a 240-sample window, reads public candles, computes momentum, applies a discrete Lotka-Volterra interaction, and emits predation pressure. No private database, no hidden server state, no parameter that cannot be inspected.

app/lotka/kernel.ts
verbatim from the public repository
// app/lotka/kernel.ts
// lotka — zero-backend predator-prey market tracker
// runs in the browser after public candles are fetched by a tiny API route.
// no database. no private state. every number below is visible.

export const WINDOW = 240;

type Candle = {
  time: number;
  close: number;
  volume: number;
};

type LotkaPoint = {
  minute: string;
  crypto: number;
  equity: number;
  pressure: number;
};

const ALPHA = 0.045;      // prey growth term
const BETA = 0.038;       // predation drag
const DELTA = 0.041;      // predator gain from interaction
const GAMMA = 0.030;      // predator decay term
const INTERACTION_SCALE = 5200;

function clamp(value: number, min: number, max: number) {
  return Math.min(max, Math.max(min, value));
}

function sigmoid(value: number) {
  return 1 / (1 + Math.exp(-value));
}

export function momentum(candles: Candle[], base: number) {
  const logs = candles.map((candle) => Math.log1p(candle.volume));
  const averageVolume = logs.reduce((sum, value) => sum + value, 0) / logs.length;
  let state = base;

  return candles.map((candle, index) => {
    if (index === 0) return state;

    const previous = candles[index - 1];
    const returnPct = ((candle.close - previous.close) / previous.close) * 100;
    const volumeImpulse = logs[index] / Math.max(0.0001, averageVolume) - 1;

    state = clamp(
      state * 0.92 + base * 0.08 + returnPct * 9.5 + volumeImpulse * 5.5,
      8,
      112,
    );

    return state;
  });
}

export function lotkaStep(crypto: number, equity: number) {
  const interaction = (crypto * equity) / INTERACTION_SCALE;

  const nextEquity = clamp(
    equity + ALPHA * equity - BETA * interaction,
    8,
    112,
  );

  const nextCrypto = clamp(
    crypto + DELTA * interaction - GAMMA * crypto,
    8,
    112,
  );

  const pressure = clamp(
    sigmoid((nextCrypto - nextEquity) / 12 + interaction / 46) * 100,
    4,
    98,
  );

  return { nextCrypto, nextEquity, pressure };
}

export function buildSeries(cryptoCandles: Candle[], equityCandles: Candle[]): LotkaPoint[] {
  const cryptoMomentum = momentum(cryptoCandles.slice(-WINDOW), 52);
  const equityMomentum = momentum(equityCandles.slice(-WINDOW), 48);

  return cryptoMomentum.map((crypto, index) => {
    const equity = equityMomentum[index];
    const interaction = (crypto * equity) / INTERACTION_SCALE;
    const pressure = clamp(
      sigmoid((crypto - equity) / 12 + interaction / 46) * 100,
      4,
      98,
    );

    return {
      minute: new Date(cryptoCandles[index].time).toLocaleTimeString("en-US", {
        hour12: false,
        hour: "2-digit",
        minute: "2-digit",
      }),
      crypto: Number(crypto.toFixed(3)),
      equity: Number(equity.toFixed(3)),
      pressure: Number(pressure.toFixed(3)),
    };
  });
}

// thesis:
// the token is not the source of the measurement.
// the token is the cultural handle attached to a public measurement.
// fork the code, replace the candles, rerun the same kernel.

append-only console

[00:00:00] browser instrument mounted; no backend process found

[00:00:00] discrete lotka-volterra kernel loaded