Skip to content

Core Concepts and Streaming

Igor Sazonov edited this page Jul 21, 2026 · 1 revision

The core of the CoinQuant platform is its AI-driven strategy builder. You describe a trading idea in plain English, and the AI translates it into a structured, backtestable schema. Because generating these strategies takes time, the API responds using Server-Sent Events (SSE) [1].

The CoinQuant PHP SDK abstracts away the complexity of parsing SSE streams, providing you with clean PHP Generators and structured result objects.

Response Classification

When you send a prompt to CoinQuant, the AI decides the shape of the response. A "simple" prompt might result in a brief chat reply, a full market report, or a complete strategy schema.

The SDK classifies responses based on the actual events received from the stream, in the following priority order [1]:

Priority Condition Type (StreamEvent::TYPE_*)
1 Any error event, or HTTP status ≥ 400 error
2 A result event carrying strategy_id, strategy_version_id, or schema strategy
3 Any report_block or report event report
4 Only chunk text events chat
5 None of the above unknown

Always branch your application logic based on the returned $result->type, rather than what you expected to receive.

Aggregated Responses

If you don't need to process the stream in real-time (e.g., you are running a background job), you can use the prompt() method. This method consumes the entire stream, aggregates the events, and returns a single StreamResult object.

$result = $client->prompt('Generate a BTCUSDT 1h EMA crossover strategy.');

if ($result->type === \CoinQuant\Streaming\StreamEvent::TYPE_STRATEGY) {
    echo "Strategy generated!\n";
    echo "Chat ID: {$result->chatId}\n";
} elseif ($result->type === \CoinQuant\Streaming\StreamEvent::TYPE_CHAT) {
    echo "AI Reply: {$result->text}\n";
}

Real-time Streaming

To react to events as they arrive—for example, to stream text tokens directly to a user's browser—iterate over the Generator returned by streamPrompt() or streamChatMessage() [1].

use CoinQuant\Streaming\StreamEvent;

$generator = $client->streamPrompt('Explain the RSI indicator.');

foreach ($generator as $event) {
    if ($event->type === StreamEvent::TYPE_CHAT) {
        // Flush the text chunk to the output buffer
        echo $event->text;
        ob_flush();
        flush();
    } elseif ($event->type === StreamEvent::TYPE_ERROR) {
        echo "\nError: {$event->errorMessage} (Code: {$event->errorCode})";
        break;
    }
}

Schema Materialization

Sometimes, the AI will return a strategy schema (a blueprint) without a strategy_version_id. This means the strategy has been drafted but is not yet saved as a backtestable entity on the platform.

You must "materialize" this schema into a concrete strategy version using the finalizeChat() method [1].

$result = $client->prompt('Long BTCUSDT when price crosses above the 200 EMA on 1h.');

if ($result->type === 'strategy' && $result->strategyVersionId === null && $result->chatId !== null) {
    // Materialize the drafted schema
    $strategy = $client->finalizeChat(
        $result->chatId, 
        'EMA 200 Crossover', // Name
        'My first automated strategy' // Description
    );
    
    $versionId = $strategy['latest_version']['id'];
    echo "Strategy materialized! Ready to backtest: {$versionId}";
}

Complete Workflow Example

Here is a complete workflow from idea generation to materialization:

// 1. Describe the idea and let the AI draft a strategy.
$res = $client->prompt('Long BTCUSDT when price crosses above the 200 EMA on 1h, exit on cross below.');

// 2. Materialize it if it came back schema-only.
$versionId = $res->strategyVersionId
    ?? $client->finalizeChat($res->chatId, 'EMA 200 Crossover', '')['latest_version']['id'];

// 3. The $versionId is now ready to be passed to the backtesting engine.
echo "Target Version ID: " . $versionId;

Next, see the Backtesting Guide to learn how to test this strategy against historical market data.


References

[1] CoinQuant PHP SDK README

Clone this wiki locally