-
Notifications
You must be signed in to change notification settings - Fork 0
Core Concepts and Streaming
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.
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.
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";
}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;
}
}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}";
}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.