1. Go to this page and download the library: Download opencck/amphp-kalman library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
opencck / amphp-kalman example snippets
use OpenCCK\Kalman\Domain\Entity\FilterConfig;
use OpenCCK\Kalman\Domain\Entity\GatingPolicy;
use OpenCCK\Kalman\Domain\Entity\Measurement;
use OpenCCK\Kalman\Domain\Model\Finance\LocalLinearTrend;
// σ_a: velocity-noise intensity (price units / s^1.5), half spread, tick size → R
$llt = new LocalLinearTrend(sigmaA: 0.5, halfSpread: 0.05, tick: 0.01);
$filter = $llt->filter(firstPrice: 100.0, config: FilterConfig::default()->withGating(GatingPolicy::chiSquare(0.001)));
foreach ($ticks as [$exchangeTimestampNs, $price]) {
$result = $filter->step(Measurement::at($exchangeTimestampNs, [0 => $price])); // predict(dt) + correct, atomic
// $result->outcomes[0]->innovation, ->nis(); $result->logLikelihood
}
$fair = $filter->meanAt(0); // filtered price
$trend = LocalLinearTrend::trendScore($filter); // v̂ / √P_vv
use OpenCCK\Kalman\Domain\Model\Finance\EtfBasket;
$etf = new EtfBasket(
weights: [0.5, 0.3, 0.2],
sigma: [4e-6, 1e-6, 5e-7, 1e-6, 3e-6, 2e-7, 5e-7, 2e-7, 2e-6], // k×k return covariance per second
sigmaA: 0.002, // velocity noise of the constituents
premiumTheta: 0.05, premiumSigma: 0.01, // OU premium of the fund over its NAV
quoteVariances: [1e-4, 2e-4, 3e-4], // r_i for the constituent quotes
etfVariance: 5e-5, // r for the fund quote
);
$filter = $etf->filter(firstPrices: [100.0, 50.0, 20.0]);
// channels 0..k-1 are the constituents, channel k the fund; any subset per measurement is fine
$filter->step(Measurement::at($ts, [0 => 100.02, 3 => 71.9]));
$nav = $etf->nav($filter); // Σ wᵢ p̂ᵢ
use OpenCCK\Kalman\Domain\Entity\FilterForm;
use OpenCCK\Kalman\Domain\Model\Finance\PairsHedge;
$pair = new PairsHedge(qAlpha: 1e-6, qBeta: 1e-5, sigmaEps: 0.02); // y = α + β·x + ε
$filter = $pair->filter(alpha0: 0.0, beta0: 1.2, config: FilterConfig::default()->withForm(FilterForm::UD));
foreach ($ticks as [$ts, $y, $x]) {
$raw = $pair->tick($ts, $y, $x); // ['ts', 'values', 'rows'] — the observation row depends on x
$filter->step(Measurement::at($raw['ts'], $raw['values']));
}
$z = PairsHedge::zScore($filter); // standardised spread, the trading signal
use Amp\Pipeline\Queue;
use OpenCCK\Kalman\Infrastructure\Async\FilterSession;
use OpenCCK\Kalman\Infrastructure\Async\MeasurementBatcher;
use OpenCCK\Kalman\Infrastructure\Async\ReorderBuffer;
use OpenCCK\Kalman\Infrastructure\Ingest\IngestOrchestrator;
use OpenCCK\Kalman\Infrastructure\Ingest\WebsocketFeed;
use function Amp\async;
$feeds = [new WebsocketFeed($urlA, $decoderA), new WebsocketFeed($urlB, $decoderB)];
$handle = (new IngestOrchestrator($feeds))->start(); // Queue<Measurement> with back-pressure + stop()
$inbox = new Queue(1024);
$snapshots = new Queue(16);
$session = new FilterSession($filter, $inbox, $snapshots, snapshotEvery: 100);
$final = $session->start(); // owner fiber; Future<StateSnapshot>
async(static function () use ($handle, $inbox): void {
$ordered = (new ReorderBuffer(windowNs: 2_000_000))->apply($handle->queue->iterate()); // exchange-time order inside a 2 ms window
(new MeasurementBatcher(256))->pump($ordered, $inbox); // arrays of ticks per queue item: loop overhead → 0
$inbox->complete();
});
foreach ($snapshots->iterate() as $snapshot) { // broadcast / persist
// ...
}
use OpenCCK\Kalman\App\Calibration\Calibrator;
use OpenCCK\Kalman\App\Calibration\Parametrization;
$param = new Parametrization(['motion.sigmaA' => 'log', 'observation.variances.0' => 'log']);
$best = (new Calibrator($param))->calibrate($modelConfig, filterConfig: null, ticks: $history);
// $best['config'] — the model config at the innovation-likelihood maximum (Nelder–Mead)
use OpenCCK\Kalman\Domain\Metric\Momentum\Rsi;
use OpenCCK\Kalman\Domain\Metric\Liquidity\LiquidityDensity;
use OpenCCK\Kalman\Domain\Metric\Filtered\Derivative;
$rsi = new Rsi(period: 14); // Wilder's RMA, the canonical definition
foreach ($closes as $close) {
$rsi->updatePrice($timestampNs, $close);
}
$rsi->value(); // 0-100, NAN until warmed up
$series = Rsi::wilder($closes, 14); // the same definition, whole history at once
$density = LiquidityDensity::within( // size resting within 10 bps of the mid
$book->bidPrices, $book->bidSizes, $book->askPrices, $book->askSizes, bandBps: 10.0,
);
$rate = Derivative::ofSeries($timestamps, $series); // d(RSI)/dt, with its own uncertainty
$rate['rate'][-1]; // the slope, per second
$rate['tStat'][-1]; // above 2 means it is real, not noise
ini
opcache.enable_cli=1 ; for CLI workers and backtests
opcache.jit=1255
opcache.jit_buffer_size=128M
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.