PHP · REST + WebSocket · NinjaTrader 8

PHP NinjaTrader 8 API examples

Server-side PHP integration with NinjaTrader 8 over CrossTrade's REST + WebSocket API. Built-in curl for REST, Ratchet/Pawl for WebSocket.

Why PHP

Using PHP against the CrossTrade NinjaTrader API

PHP's built-in curl extension handles REST cleanly. For WebSocket, Ratchet/Pawl is the established client. GetBars returns historical OHLC data — useful for backtesting external indicators against NT8's actual price history.

REST curl extension (built-in)
WebSocket ratchet/pawl (composer require ratchet/pawl)
REST · animated

Watch the request get written

A pseudo-developer types out a real POST GetBars call against your NinjaTrader 8 account. The animation runs on a loop; the static snippet below is yours to copy.

getbars.php
Copy this

Complete PHP GetBars example

<?php

$token = "your-bearer-token";

$body = json_encode([
    "periodType" => "Minute",
    "period"     => 5,
    "fromDate"   => "2026-05-26T13:30:00Z",
    "toDate"     => "2026-05-26T20:00:00Z",
]);

$ch = curl_init("https://app.crosstrade.io/v1/api/accounts/Sim101/instruments/ES%2012-25/bars");
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer $token",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS     => $body,
    CURLOPT_RETURNTRANSFER => true,
]);

$res = json_decode(curl_exec($ch), true);
echo count($res["bars"]) . " bars\n";
WebSocket · animated

Streaming data with ratchet/pawl (composer require ratchet/pawl)

Same flow on a persistent connection: open the socket, send a subscribe message, receive market data or P&L pushes in real time. CrossTrade's WebSocket is at wss://app.crosstrade.io/ws/stream with the same Bearer token in the request header.

stream.php
Copy this

Complete PHP WebSocket example

<?php
require "vendor/autoload.php";

use Ratchet\Client\Connector;
use React\EventLoop\Loop;

$connector = new Connector(Loop::get());
$connector("wss://app.crosstrade.io/ws/stream", [], [
    "Authorization" => "Bearer YOUR_TOKEN",
])->then(function ($ws) {
    $ws->send(json_encode([
        "action" => "subscribe",
        "instruments" => ["ES 12-25"],
    ]));

    $ws->on("message", function ($msg) {
        echo $msg . "\n";
    });
});

Loop::run();

The full PHP-compatible API surface

Every endpoint documented with request/response schemas, error codes, rate-limit notes, and language-specific code samples.

FAQ

Common questions

Is PHP a good choice for algorithmic trading?

Yes, particularly when CrossTrade is connecting to an existing PHP web stack — a Laravel admin panel, a Symfony account dashboard, a WordPress widget that shows current positions. PHP 8.x is fast (JIT), modern (typed properties, enums), and the built-in curl extension handles CrossTrade REST cleanly without any composer dependency.

Laravel integration?

Yes — use Http::withToken($token)->post(...) for REST. Store the token in config/services.php sourcing from .env. For WebSocket, run a long-running queue worker (php artisan queue:work) with Ratchet/Pawl as the client. Wrap CrossTrade calls as a service class bound in a service provider.

Guzzle or the built-in curl extension?

Both work. Built-in curl is zero-dependency and ideal for scripts/cron. Guzzle adds middleware (retries, logging, exception handling) and is what Laravel's HTTP client wraps. For production trading code, Guzzle's middleware story usually wins — easier to bolt on retry-with-backoff.

Long-running processes: Swoole or RoadRunner?

Both work for keeping a WebSocket open. Swoole rewrites PHP into an async-capable runtime — pair it with workerman or its own coroutine API for the CrossTrade WebSocket. RoadRunner does similar but is Go-backed. Pick based on team familiarity.

Symfony integration?

Yes — use the HttpClient component for REST (zero-dependency, same Bearer-token pattern). For WebSocket, the Ratchet/Pawl client works inside a Symfony Console long-running command. Bind everything as services in services.yaml.

Performance vs Python or Node?

PHP 8.3 with JIT is competitive with Node for typical web/trading workloads. Network-bound calls (CrossTrade REST) don't exercise the JIT much — both languages finish well under CrossTrade's ~50ms round-trip. For pure CPU-bound work (heavy backtest math), the JIT gives PHP a real boost over PHP 7.x.

WordPress integration?

Yes — write a small plugin that calls CrossTrade endpoints and surfaces positions / orders / P&L in the dashboard. Use WordPress transients to cache responses (CrossTrade's 3 req/sec rate limit is easy to hit if every admin page load fires a fresh request).

Can I keep composer dependencies minimal?

Yes — the REST examples use only the built-in curl extension. For WebSocket you do need composer require ratchet/pawl. If you want to avoid the dependency, you can use raw fsockopen / stream_socket_client for a basic WebSocket — works but you re-implement the protocol yourself.

Testing with PHPUnit?

Yes — mock the HTTP client (Guzzle's MockHandler for Guzzle, or wrap curl_exec in a tiny abstraction). For integration tests, hit Sim101 against a test token. CrossTrade's consistent JSON error shape makes assertion-writing straightforward.

Build your first NinjaTrader 8 trading bot in PHP

One bearer token, one URL, every NinjaTrader endpoint. Ship to Sim101 first.