Playground API
The Playground API powers the Algo Playground experience. It provides endpoints for browsing strategy templates, running backtests, controlling playback speed, and managing saved strategies with full CRUD operations.
Base path
https://api.test-max.com/api/playground/Authentication
The Playground API uses cookie-based JWT authentication — the same session cookie set when you log into the TestMax web app. No API key is needed.
Access requirements
| Endpoint | Access |
|---|---|
GET /templates | Public (no auth required) |
| All other endpoints | Pro plan required |
Templates
GET /api/playground/templates
List all available strategy templates. This endpoint is public and does not require authentication.
URL: GET /api/playground/templates
Authentication: None required.
Response
{ "success": true, "errorCode": 0, "errorMessage": null, "templates": [ { "id": "sma-crossover", "name": "SMA Crossover", "description": "A moving average crossover strategy that goes long when the fast SMA crosses above the slow SMA.", "category": "trend-following", "difficulty": "beginner", "params": [ { "name": "fast_period", "label": "Fast SMA Period", "type": "number", "default": 10, "min": 2, "max": 100 }, { "name": "slow_period", "label": "Slow SMA Period", "type": "number", "default": 20, "min": 5, "max": 200 } ] }, { "id": "rsi-scalper", "name": "RSI Scalper", "description": "A mean-reversion scalping strategy using RSI oversold/overbought signals.", "category": "mean-reversion", "difficulty": "beginner", "params": [ { "name": "rsi_period", "label": "RSI Period", "type": "number", "default": 14, "min": 2, "max": 50 }, { "name": "oversold", "label": "Oversold Level", "type": "number", "default": 30, "min": 5, "max": 50 }, { "name": "overbought", "label": "Overbought Level", "type": "number", "default": 70, "min": 50, "max": 95 } ] } ]}Template fields
| Field | Type | Description |
|---|---|---|
id | string | Unique template identifier. Pass this as templateId when running a backtest. |
name | string | Human-readable template name |
description | string | What the strategy does |
category | string | Strategy category (e.g., "trend-following", "mean-reversion", "breakout") |
difficulty | string | Difficulty level: "beginner", "intermediate", or "advanced" |
params | array | Configurable parameters for the template |
Parameter fields
| Field | Type | Description |
|---|---|---|
name | string | Parameter key used in the strategy code |
label | string | Display label for the UI |
type | string | Data type: "number", "string", or "boolean" |
default | any | Default value |
min | number or null | Minimum value (for number params) |
max | number or null | Maximum value (for number params) |
Example
curl https://api.test-max.com/api/playground/templatesconst response = await fetch("https://api.test-max.com/api/playground/templates");const data = await response.json();
for (const template of data.templates) { console.log(`${template.name} (${template.difficulty}): ${template.description}`);}Execution
POST /api/playground/run
Run a backtest. You can run a template with custom parameters or provide custom Python code.
URL: POST /api/playground/run
Authentication: Cookie-based JWT. Pro plan required.
Request body
{ "templateId": "sma-crossover", "code": null, "instrument": "NQ", "startDate": "2025-01-15", "endDate": "2025-01-15", "timeframe": "5m", "params": { "fast_period": 10, "slow_period": 25 }, "contextTimeframes": ["15m", "1h"]}| Field | Type | Required | Description |
|---|---|---|---|
templateId | string or null | Conditional | Template to run. Required if code is not provided. |
code | string or null | Conditional | Custom Python strategy code. Required if templateId is not provided. |
instrument | string | Yes | Instrument symbol (e.g., "NQ", "ES", "GC") |
startDate | string | Yes | Start date in YYYY-MM-DD format |
endDate | string or null | No | End date. Defaults to end of the start date session. |
timeframe | string | Yes | Bar timeframe (e.g., "1m", "5m", "15m") |
params | object or null | No | Parameter overrides for the template. Keys must match template param names. |
contextTimeframes | array or null | No | Additional timeframes for multi-timeframe analysis (e.g., ["15m", "1h"]) |
Response
{ "success": true, "errorCode": 0, "errorMessage": null, "executionId": "exec_abc123", "status": "running"}| Field | Type | Description |
|---|---|---|
executionId | string | Unique identifier for this execution. Use to track status. |
status | string | Initial status: "running" |
Example
const response = await fetch("https://api.test-max.com/api/playground/run", { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", // Include session cookie body: JSON.stringify({ templateId: "sma-crossover", instrument: "NQ", startDate: "2025-01-15", timeframe: "5m", params: { fast_period: 8, slow_period: 21 }, }),});
const data = await response.json();console.log(`Execution started: ${data.executionId}`);Limits
| Limit | Value |
|---|---|
| Max concurrent executions per user | 1 |
| Execution timeout | 10 minutes |
| Max script size | 200 KB |
POST /api/playground/stop
Stop a running backtest execution.
URL: POST /api/playground/stop
Authentication: Cookie-based JWT. Pro plan required.
Request body
{}No body fields are required. The server stops the current user’s active execution.
Response
{ "success": true, "errorCode": 0, "errorMessage": null}POST /api/playground/speed
Set the playback speed for a running backtest.
URL: POST /api/playground/speed
Authentication: Cookie-based JWT. Pro plan required.
Request body
{ "speed": 25}| Field | Type | Required | Description |
|---|---|---|---|
speed | number | Yes | Speed multiplier from 1 (slowest) to 50 (fastest) |
Response
{ "success": true, "errorCode": 0, "errorMessage": null}Strategies
GET /api/playground/strategies
List all saved strategies for the authenticated user.
URL: GET /api/playground/strategies
Authentication: Cookie-based JWT. Pro plan required.
Response
{ "success": true, "errorCode": 0, "errorMessage": null, "strategies": [ { "id": "strat_abc123", "name": "My SMA Strategy", "instrument": "NQ", "timeframe": "5m", "createdAt": "2025-01-10T08:30:00Z", "updatedAt": "2025-01-14T16:45:00Z" } ]}| Field | Type | Description |
|---|---|---|
strategies | array | List of saved strategy summaries |
strategies[].id | string | Unique strategy ID |
strategies[].name | string | Strategy name |
strategies[].instrument | string | Default instrument |
strategies[].timeframe | string | Default timeframe |
strategies[].createdAt | string | ISO 8601 creation timestamp |
strategies[].updatedAt | string | ISO 8601 last-modified timestamp |
POST /api/playground/strategies/save
Save a new strategy or update an existing one.
URL: POST /api/playground/strategies/save
Authentication: Cookie-based JWT. Pro plan required.
Request body
{ "name": "My Custom Strategy", "code": "# Strategy code here\nfor i in range(MAX_BARS):\n bar = get_next_bar()\n ...", "instrument": "NQ", "timeframe": "5m", "params": { "fast_period": 10, "slow_period": 25, "stop_loss": 20 }}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Strategy name |
code | string | Yes | Full Python strategy code |
instrument | string | Yes | Default instrument symbol |
timeframe | string | Yes | Default timeframe |
params | object | Yes | Default parameter values |
Response
{ "success": true, "errorCode": 0, "errorMessage": null, "id": "strat_abc123"}| Field | Type | Description |
|---|---|---|
id | string | The ID of the saved strategy (new or updated) |
GET /api/playground/strategies/:id
Get a saved strategy by ID, including the full code and parameters.
URL: GET /api/playground/strategies/:id
Authentication: Cookie-based JWT. Pro plan required.
URL parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Strategy ID |
Response
{ "success": true, "errorCode": 0, "errorMessage": null, "strategy": { "id": "strat_abc123", "name": "My Custom Strategy", "code": "# Strategy code here...", "instrument": "NQ", "timeframe": "5m", "params": { "fast_period": 10, "slow_period": 25, "stop_loss": 20 }, "createdAt": "2025-01-10T08:30:00Z", "updatedAt": "2025-01-14T16:45:00Z" }}DELETE /api/playground/strategies/:id
Delete a saved strategy.
URL: DELETE /api/playground/strategies/:id
Authentication: Cookie-based JWT. Pro plan required.
URL parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Strategy ID to delete |
Response
{ "success": true, "errorCode": 0, "errorMessage": null}GET /api/playground/strategies/:id/runs
Get the run history for a saved strategy. Returns past backtest executions with their results.
URL: GET /api/playground/strategies/:id/runs
Authentication: Cookie-based JWT. Pro plan required.
URL parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Strategy ID |
Response
{ "success": true, "errorCode": 0, "errorMessage": null, "runs": [ { "id": "run_xyz789", "strategyId": "strat_abc123", "instrument": "NQ", "timeframe": "5m", "startDate": "2025-01-15", "endDate": "2025-01-15", "status": "completed", "totalPnl": 1250.00, "totalTrades": 8, "winRate": 62.5, "params": { "fast_period": 10, "slow_period": 25 }, "startedAt": "2025-01-15T10:00:00Z", "completedAt": "2025-01-15T10:02:34Z" } ]}| Field | Type | Description |
|---|---|---|
runs | array | List of past backtest runs |
runs[].id | string | Unique run ID |
runs[].strategyId | string | Parent strategy ID |
runs[].instrument | string | Instrument traded |
runs[].timeframe | string | Bar timeframe used |
runs[].startDate | string | Backtest start date |
runs[].endDate | string | Backtest end date |
runs[].status | string | Run status: "completed", "failed", "stopped", or "timeout" |
runs[].totalPnl | number | Net P&L in USD |
runs[].totalTrades | number | Number of round-trip trades |
runs[].winRate | number | Win percentage (0-100) |
runs[].params | object | Parameters used for this run |
runs[].startedAt | string | ISO 8601 timestamp when the run started |
runs[].completedAt | string or null | ISO 8601 timestamp when the run completed (null if still running) |