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. ```php $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]. ```php 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]. ```php $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: ```php // 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](Backtesting-Guide.md) to learn how to test this strategy against historical market data. --- ### References [1] [CoinQuant PHP SDK README](https://github.com/tigusigalpa/coinquant-php/blob/main/README.md)