API and MCP
HTTP API for managing the bot and the tester: settings, strategies, exchange API keys, positions and orders, logs, running the tester and working with its reports. The bot also works as an MCP server — an AI assistant can check the bot's state, run research in the tester and manage strategies on its own.
The address is the same as the web interface: http://<host>:<port>. The port is set by
the port field in settings_program.json.
Access Requests and responses Endpoints Tester MCP for AI assistants Response codes
Access
API token (recommended)
Send the Authorization: Bearer <api_token> header with every request:
curl -H "Authorization: Bearer <api_token>" http://127.0.0.1:5000/api/current/bots
The bot creates api_token itself on first start and stores it in
settings_program.json. The token works from any address and with any auth_telegram
value, and a browser login does not reset it.
You can view and copy the token in the web interface: "Global Config", the "API and MCP token" block. The
"Issue new" button is there too — the old token stops working immediately. With Telegram login disabled,
this block works only from the same machine (127.0.0.1).
In the config editor, in the log and in the GET /api/settings/config response the token is
masked (the last 4 characters are visible), and it cannot be changed through the editor or
POST /api/settings/config. A new token via the API:
POST /api/settings/api-token/regenerate, response
{ "success": true, "api_token": "..." }.
⚠️ Keep the token like a password: it gives access to everything, including trading and exchange keys.
Without a token, from the same machine
If Telegram login is disabled ("auth_telegram": false), requests without a token are accepted
only from the same machine at 127.0.0.1 or localhost:
curl http://127.0.0.1:5000/api/current/bots
From other addresses without a token the API returns 401. With login disabled the web
interface is still open to anyone who can connect to the port, so keep login enabled on a server with an
open port.
Requests from other websites
A POST with an Origin header that does not match the bot's address is rejected with
403 — this is CSRF protection. curl, scripts and MCP clients do not send
Origin, so this does not affect them. If the bot is behind a reverse proxy, the proxy must pass
the original Host header.
Login cookie
Instead of the token you can send the hamster-bot-token cookie if Telegram login is
enabled:
POST /htmx/login/get-token— the bot sends a one-time code to Telegram.POST /htmx/login/verifywith the formtoken_enter=<code>— the response contains the headerSet-Cookie: hamster-bot-token=...- Send the cookie with requests:
curl -b "hamster-bot-token=<value>" ...
The cookie is valid for up to 10 days. Only the latest login is valid: a new login (including from a browser) invalidates the previous cookie.
Requests and responses
- POST request bodies are UTF-8 JSON (
Content-Type: application/json). - Names in the path are URL-encoded: strategy
T4 BTC→/api/settings/strategy/T4%20BTC. - Settings and configs are sent and returned in the same form as in the bot's JSON files.
- A successful action returns
{ "success": true, ... }, an error returns{ "success": false, "error": "error text" }with a code from the response codes table. - A bot is identified by account and strategy name:
/{accountName}/{settingsName}. If the strategy trades several pairs, the?symbol=parameter picks the pair; without it the first one is used.
Example: create a strategy from a draft with default values.
curl -X POST http://127.0.0.1:5000/api/settings/strategy/draft \
-H "Content-Type: application/json" \
-d '{ "account": "main", "symbol": "BTCUSDT", "strategy": "zigzag", "time_frame": "1h" }'
The draft saves nothing: edit the returned object and send it to POST /api/settings/strategy —
the strategy is saved and starts right away.
curl -X POST http://127.0.0.1:5000/api/bots/main/T4%20BTC/pause
{ "success": true, "name": "T4 BTC", "is_runing": false }
Endpoints
Under each endpoint description there is a collapsed request and response example.
Settings
| GET | /api/settings/config | Global config (settings_program.json). The Telegram bot token is masked: the first 4 characters are visible. api_token is masked: the last 4 characters are visible
Example{
"name": "MyBot",
"use_web": true,
"port": 5000,
"api_token": "••••••••••••b9c2",
"telegram": {
"bot_token": "1234************",
"id_chat": 123456789
}
}
|
| POST | /api/settings/config | Change the config: send only the fields that change, applied immediately. The Telegram bot token and api_token are not changed here: these fields in the body are ignored
ExampleRequest: { "name": "MyBot", "chart": { "count": 500 } }
Response: { "success": true }
|
| POST | /api/settings/api-token/regenerate | Issue a new api_token, the old one stops working immediately. The only API response where the token is shown in full. No body needed
Example{ "success": true, "api_token": "<new token>" }
|
| GET | /api/settings/hints/{kind} | Settings field descriptions: settings, config_tester, settings_program. Parameters ?lang= (en, ru, pt), ?filter=
ExampleRequest: GET /api/settings/hints/config_tester?filter=parameter_mining,monte_carlo Response — an object "dotted field path → description": {
"parameter_mining": "List of parameters to mine. Each has a name (parameter path) and either a start/end/step range or a values list...",
"monte_carlo": "Mining limit: if there are more combinations than this number, a random sample of this size is used..."
}
|
Strategies
| GET | /api/settings/strategy | All bot strategies
Example[
{
"name": "T4 BTC",
"is_runing": true,
"exchange": { "name": "binance", "account": "main" },
"basic": { "symbol": "BTCUSDT", "strategy": "zigzag", "time_frame": "1h" }
}
]
|
| GET | /api/settings/strategy/{name} | One strategy by name (case-insensitive) |
| POST | /api/settings/strategy/draft | Draft with default values for an account, saves nothing
ExampleRequest: { "account": "main", "symbol": "BTCUSDT", "strategy": "zigzag", "time_frame": "1h", "account_type": "UNIFIED" }
Instead of |
| POST | /api/settings/strategy | Create or change a strategy, changes apply immediately. ?old_name= — rename
ExampleRequest (the body is a strategy object): POST /api/settings/strategy?old_name=T4%20BTC Response ( { "success": true, "name": "T4 BTC v2", "created": false }
|
| POST | /api/settings/strategy/{name}/copy | Copy under a new name, saved and started
ExampleRequest ( { "new_name": "T4 ETH", "new_symbol": "ETHUSDT" }
Response: { "success": true, "name": "T4 ETH" }
|
| POST | /api/settings/strategy/{name}/delete | Delete a strategy, orders and position are left untouched. ?full=1 — cancel orders and close the position first
ExampleRequest: POST /api/settings/strategy/T4%20BTC/delete?full=1 Response: { "success": true }
If with |
Accounts (exchange API keys)
| GET | /api/settings/accounts | All accounts
Example[
{
"name": "main",
"exchange": "binance",
"api_key": "...",
"api_secret": "...",
"is_encrypted": true
}
]
|
| GET | /api/settings/accounts/{name} | One account |
| GET | /api/settings/accounts/{name}/symbols | Pairs available on the exchange for the account
Example["BTCUSDT", "ETHUSDT"] |
| POST | /api/settings/accounts | Create or change an account, keys are sent in plain text. ?old_name= — rename
ExampleRequest: { "name": "main", "exchange": "binance", "api_key": "...", "api_secret": "...", "is_encrypted": true, "open_positions_limiter": 0 }
Response ( { "success": true, "name": "main", "applied": 3 }
With |
| POST | /api/settings/accounts/{name}/delete | Delete an account |
| GET | /api/current/accounts/{name}/info | Account and key data from the exchange, updated hourly (needs a running bot on the account)
Example{
"name": "main",
"exchange": "binance",
"api_key": "abc1****",
"account_type": "UNIFIED",
"symbol": "BTCUSDT",
"ok": true,
"status": "OK",
"warnings": [],
"rows": [ { "name": "Permissions", "value": "..." } ],
"updated_utc": "2026-10-25T12:00:00Z"
}
|
| GET | /api/current/accounts/{name}/balance-history | Balance history, ?max= — at most this many points (default 5000)
Example{
"account": "main",
"total": 12000,
"points": [ { "time": 1761393600, "margin": 1234.5, "wallet": 1200.0, "positions": "..." } ]
}
|
| POST | /api/current/accounts/{name}/balance-history/compact | Compact the balance history now using the monitoring settings
Example{ "success": true, "message": "...", "points_before": 12000, "points_after": 3000, "bytes_before": 512000, "bytes_after": 128000 }
|
Bots
| GET | /api/current/bots | Summary of all bots: status, price, position, order count, exchange sync
Example[
{
"account": "main",
"exchange": "binance",
"strategy": "T4 BTC",
"strategy_code": "zigzag",
"symbol": "BTCUSDT",
"time_frame": "1h",
"is_runing": true,
"is_live": true,
"status_text": "...",
"last_price": 65500.0,
"last_bar_time": "2026-10-25T12:00:00",
"last_sync_utc": "2026-10-25T12:00:05Z",
"sync_missed_cycles": 0,
"position": { "side": "Buy", "size": 0.01, "entry_price": 65000.0, "cost": 650.0, "unrealized_pnl": 5.0 },
"orders": 2
}
]
|
| GET | /api/current/balances | Wallet and margin balance per key, spot and futures separately. ?account=
ExampleRequest: GET /api/current/balances?account=main Response: [
{ "account": "main", "exchange": "bybit", "type": "futures", "wallet": 1234.56, "margin": 1180.20 },
{ "account": "main", "exchange": "bybit", "type": "spot", "wallet": 500.00, "margin": 500.00 }
]
For spot both values are the USDT balance. Balances come from running bots: an account without a running bot is not listed. |
| GET | /api/current/bots/{accountName}/{settingsName}/bars | Bot candles, ?limit= — last N (default 500)
ExampleRequest: GET /api/current/bots/main/T4%20BTC/bars?limit=100 The response is an array of candles with fields |
| GET | /api/current/ubots/api/current/ubots/{accountName}/{settingsName} | Full state snapshot. The format may change between versions — for a permanent integration use bots, positions, orders |
| POST | /api/bots/pause-all/api/bots/play-all | Pause / start all bots
Example{ "success": true, "count": 5 }
|
| POST | /api/bots/{accountName}/{settingsName}/pause/api/bots/{accountName}/{settingsName}/play | Pause / start a strategy (for a multi-pair strategy — all its pairs)
ExampleRequest: POST /api/bots/main/T4%20BTC/pause Response (for { "success": true, "name": "T4 BTC", "is_runing": false }
|
| POST | /api/bots/{accountName}/{settingsName}/send-chart | Send the bot chart to Telegram |
| POST | /api/bots/{accountName}/{settingsName}/send-position | Send a summary to Telegram: balance, position, PnL, orders |
Positions and orders
| GET | /api/current/positions | Positions of all bots
Example[
{
"account": "main",
"exchange": "binance",
"strategy": "T4 BTC",
"symbol": "BTCUSDT",
"position": {
"Symbol": "BTCUSDT",
"Side": "Buy",
"Size": 0.01,
"EntryPrice": 65000.0,
"Cost": 650.0,
"UnrealizedPnl": 12.5,
"Leverage": 10,
"Cross": false
}
},
{
"account": "sub1",
"exchange": "binance",
"strategy": "T3 ETH",
"symbol": "ETHUSDT",
"position": null
}
]
|
| GET | /api/current/orders | Open orders of all bots
Example[
{
"account": "main",
"exchange": "binance",
"strategy": "T4 BTC",
"symbol": "BTCUSDT",
"order": {
"Id": "order-123",
"client_id": "cl-456",
"Market": "BTCUSDT",
"Side": "Buy",
"Type": "Limit",
"Status": "New",
"Size": 0.01,
"filledSize": 0.0,
"remainingSize": 0.01,
"Price": 64000.0,
"TriggerPrice": null,
"ReduceOnly": false
}
}
]
|
| POST | /api/trading/market | Market order on an account. The pair must be traded by one of the account's bots
ExampleRequest ( { "account": "main", "symbol": "BTCUSDT", "side": "Buy", "size": 0.01 }
Response: { "success": true, "order_id": "order-123" }
|
| POST | /api/positions/{accountName}/{settingsName}/close | Close the bot's position
ExampleRequest: POST /api/positions/main/T4%20BTC/close Response: { "success": true }
|
| POST | /api/positions/{accountName}/close-all | Close all positions of the account
Example{ "success": true, "count": 3 }
|
| POST | /api/positions/{accountName}/reduce | Reduce all positions of the account by percent (1–100)
ExampleRequest: { "percent": 50 }
Response: { "success": true, "count": 3 }
|
| POST | /api/orders/{accountName}/{settingsName}/{orderId}/cancel | Cancel one order (regular or stop order)
ExampleRequest: POST /api/orders/main/T4%20BTC/order-123/cancel Response: { "success": true }
|
| POST | /api/orders/{accountName}/cancel-all | Cancel all orders of the account
Example{ "success": true, "count": 2 }
|
| POST | /api/orders/cancel-all | Cancel all orders on all accounts
Example{ "success": true, "count": 7 }
|
System and logs
| GET | /api/system/status | Program version, server resources, bot counters
Example{
"program": "hamster-bot",
"version": "2026/10/23",
"name": "MyBot",
"type": "bot",
"os": "Linux 6.1",
"architecture": "X64",
"machine": "srv1",
"runtime": ".NET 8.0",
"processors": 4,
"uptime_sec": 86400,
"cpu_percent": 12.5,
"memory_total_bytes": 8589934592,
"memory_available_bytes": 4294967296,
"process_memory_bytes": 314572800,
"disk": "/",
"disk_total_bytes": 107374182400,
"disk_free_bytes": 53687091200,
"accounts": 2,
"strategies": 5,
"bots": 6,
"bots_running": 5,
"auto_update_supported": true
}
|
| POST | /api/system/shutdown | Shut down the program (only with Telegram login) |
| POST | /api/system/update | Start a program update (see auto_update_supported in the status) |
| GET | /api/logs | Latest lines of the main log (array of strings), ?tail= |
| GET | /api/logs/errors | Errors for the last ?hours= hours (default 24, up to 48), ?warnings=1 — with warnings
Example[
{
"level": "Error",
"first_utc": "2026-10-25T08:00:00Z",
"last_utc": "2026-10-25T12:00:00Z",
"count": 3,
"source": "T4 BTC",
"message": "...",
"exception": "..."
}
]
Identical messages are merged, |
| GET | /api/logs/files | Log files, newest first
Example[ { "name": "log_25-10-2026.log", "size": 102400, "modified_utc": "2026-10-25T12:00:00Z" } ]
|
| GET | /api/logs/files/{filename} | Log file contents as text, ?download=1 — download |
Tester
| GET | /api/tester/status | Tester state: runs, single runs, data download
Example{
"run": {
"active": true,
"status": "Running",
"started_utc": "2026-10-25T12:00:00Z",
"finished_utc": null,
"message": "API mining run",
"runs_done": 40,
"runs_total": 120,
"current_bar": 5000,
"total_bars": 20000,
"parallel": false
},
"wizard_runs": [
{
"run_id": "a1b2c3d4",
"strategies": ["T4 BTC"],
"status": "Completed",
"started_utc": "2026-10-25T11:00:00Z",
"finished_utc": "2026-10-25T11:02:00Z",
"current_bar": 20000,
"total_bars": 20000,
"message": "Completed: 1 strategies."
}
],
"download": { "active": false, "status": "Idle", "started_utc": null, "finished_utc": null, "message": "" },
"settings_folder": ""
}
|
| GET POST | /api/tester/config | Tester config (config_tester.json): period, fees, mining parameters. POST — the whole config |
| GET | /api/tester/exchanges/api/tester/exchanges/{exchange}/symbols | Exchanges with historical data and their pairs. An empty pair list means the exchange is unavailable right now
Example["bybit", "binance", ...] |
| GET | /api/tester/settings/api/tester/settings/{name} | Tester strategy settings in the current folder
Example[ { "name": "T4 BTC", "exchange": "bybit", "symbol": "BTCUSDT", "symbols": null, "strategy": "zigzag", "time_frame": "1h" } ]
|
| POST | /api/tester/settings/draft | Settings draft, saves nothing
ExampleRequest: { "exchange": "bybit", "symbol": "BTCUSDT", "strategy": "zigzag", "time_frame": "1h" }
Instead of |
| POST | /api/tester/settings | Save settings, ?old_name= — rename. Existing settings with the same name are not overwritten
Example{ "success": true, "name": "T4 BTC" }
|
| POST | /api/tester/settings/{name}/copy/api/tester/settings/{name}/delete | Copy (also to another exchange or pair) / delete
Example
{ "new_name": "T4 BTC binance", "new_exchange": "binance", "new_symbol": "" }
Response: { "success": true, "name": "T4 BTC binance" }
|
| GET POST | /api/tester/settings-folder | Current tester settings folder and switching to another one ("" — the main folder)
ExampleGET — response ( { "path": "", "folders": [ { "name": "2026-10", "settings": 12 } ] }
POST — request: { "path": "2026-10" }
POST — response: { "success": true, "path": "2026-10" }
|
| POST | /api/tester/run | Parameter mining (parameter_mining)
ExampleRequest ( { "settings": ["T4 BTC", "T4 ETH"], "config": { ... } }
Response: { "success": true }
|
| POST | /api/tester/stress | Stress test: the same settings under worse execution conditions. Body and responses as for /api/tester/run |
| POST | /api/tester/wizard-run | Single run. Body as for /api/tester/run
Example{ "success": true, "run_id": "a1b2c3d4" }
Progress is in |
| POST | /api/tester/snapshot-run | Repeat a run from a snapshot file (?root=&path=). The body is optional: a modified snapshot applies only to this run
ExamplePOST /api/tester/snapshot-run?root=report&path=T4/run_snapshot_20261025.json |
| POST | /api/tester/download-data | Download historical data for all tester settings |
| GET | /api/tester/wizard-results | Single run results, newest first: metrics and report paths
Example[
{
"runId": "a82c93c5",
"timestamp": "2026-10-25T05:26:50Z",
"strategies": ["T4 BTC"],
"stats": {
"InitialBalance": 10000.0, "FinalBalance": 9581.25, "TotalPnL": -418.75, "TotalPnLPercent": -4.19,
"TotalTrades": 23, "WinRate": 13.04, "MaxDrawdown": 527.89, "MaxDrawdownPercent": 5.26, "TotalFees": 22.2
},
"chartUrl": "/tester-report/T4/T4_run_001_of_001_BTCUSDT_1h_ee8c3c2e.html",
"report_path": "T4/T4_run_001_of_001_BTCUSDT_1h_ee8c3c2e.html",
"report_json_path": "T4/T4_run_001_of_001_BTCUSDT_1h_ee8c3c2e.json",
"period": "2025-09-01 .. 2025-09-20",
"elapsed": "00:00:07"
}
]
|
| GET | /api/tester/files | Tester folders: ?root=report|data|runs&path=
Example{
"root": "report",
"path": "T4",
"items": [
{ "name": "old", "is_dir": true, "size": 204800, "modified_utc": "2026-10-20T10:00:00Z", "snapshot": false, "editable": false },
{ "name": "run_snapshot_20261025.json", "is_dir": false, "size": 51200, "modified_utc": "2026-10-25T12:00:00Z", "snapshot": true, "editable": false }
]
}
|
| GET POST | /api/tester/files/download/api/tester/files/delete/api/tester/files/content/api/tester/files/save | Download, delete, read a snapshot, save JSON in runs (?root=&path=) |
| GET | /api/tester/reports/summary | Report summaries for comparison: metrics and equity curve, ?r= can be repeated
ExampleRequest: GET /api/tester/reports/summary?r=T4/report.html&r=T4_STRESS/report.html Response: [
{
"report": "T4/report.html",
"created": "2026-10-25T12:00:00Z",
"summary": {
"name_comment": "T4",
"start": "2025-01-01T00:00:00",
"end": "2026-01-01T00:00:00",
"symbols": ["BTCUSDT"],
"metrics": { "TotalPnLPercent": 42.1, "MaxDrawdownPercent": 12.3, "ProfitFactor": 1.8, "WinRate": 55.0, "TotalTrades": 120 },
"equity_t": [1735689600],
"equity_v": [1000.0]
}
}
]
|
| GET | /api/tester/reports/json | Detailed run results in compact JSON: ?path=, ?sections=, ?trades_offset=, ?trades_limit=
ExampleRequest: GET /api/tester/reports/json?path=T4/T4_run_001_of_001_BTCUSDT_1h_ee8c3c2e.html§ions=by_symbol,trades&trades_limit=2 Response: {
"v": 1,
"created_utc": "2026-10-25T05:45:34Z",
"html_report": "T4_run_001_of_001_BTCUSDT_1h_ee8c3c2e.html",
"by_symbol": [
{ "symbol": "BTCUSDT", "strategy": "zigzag", "trades": 23, "win_rate": 13.04, "profit_factor": 0.395, "pnl": -390.14,
"best_trade": 160.02, "worst_trade": -57.7, "max_drawdown_incl_unrealized": -483.2, "buy_hold_percent": 6.81,
"fee": 22.2, "volume": 221995.16, "position_avg_percent": 49.31, "position_max_percent": 50.72 }
],
"trades": {
"count": 23,
"columns": ["symbol", "side", "open", "close", "holding_hours", "fills", "net_pnl", "mae", "mfe"],
"rows": [
["BTCUSDT", "short", "2025-09-01 00:04", "2025-09-01 07:54", 7.83, 2, -57.6968, -57.6968, 38.8311],
["BTCUSDT", "long", "2025-09-01 07:54", "2025-09-01 20:45", 12.85, 2, -46.2855, -50.7967, 26.7293]
],
"offset": 0
}
}
In |
| GET | /api/tester/publish/files | Files of a report folder that can be published on the website, ?path=
Example[ { "name": "reports_history.csv", "size": 10240, "kind": "history" } ]
|
| POST | /api/tester/publish | Send the selected files to the website, the publication appears after moderation
ExampleRequest ( { "path": "T4", "files": ["reports_history.csv"], "contact": "@telegram", "comment": "...", "agree": true }
Response: { "success": true, "sent": ["reports_history.csv"] }
|
Tester via API
- All runs work in the background: the response comes immediately, progress and result are in
GET /api/tester/status. - Parameter mining, stress test and snapshot replay run one at a time. Single runs can run in parallel.
While historical data is downloading the tester does not start, and vice versa — the response is
409. - A running mining job cannot be stopped, so check the number of combinations in advance (or set
monte_carlo— a random sample). - Mining results go to
report/<name_comment>:reports_history.csvwith the metrics of each combination, HTML and JSON reports, the optimizer summary report. Give each experiment its ownname_comment. - The JSON report (
report.enable_json_report) has the same numbers as the HTML report but is dozens of times smaller: sectionsrun,metrics,by_symbol,monthly,trades,curves,settings.
MCP for AI assistants
The bot works as an MCP server (Model Context Protocol): an AI assistant — Claude and other MCP clients — can check the bot's state, run the tester and manage strategies on its own. MCP tools mirror the API and follow the same access rules.
Enabling
MCP is off by default. Enable it in settings_program.json:
{ "use_mcp": true }
The change takes effect immediately, no restart needed. It can also be done via the API:
POST /api/settings/config with the body { "use_mcp": true }. While MCP is off,
/mcp returns 404.
Address: http://127.0.0.1:<port>/mcp, Streamable HTTP transport.
Connecting to Claude Code
claude mcp add --transport http hamster-bot http://127.0.0.1:5000/mcp --header "Authorization: Bearer <api_token>"
Or in the project's .mcp.json file:
{
"mcpServers": {
"hamster-bot": {
"type": "http",
"url": "http://127.0.0.1:5000/mcp",
"headers": { "Authorization": "Bearer <api_token>" }
}
}
}
Other clients connect to the same address if they support Streamable HTTP and custom request headers.
Access and safety
- Access is the same as for the API (see Access): the
Authorization: Bearer <api_token>header from any address; without it — thehamster-bot-tokencookie with login enabled, or only from the same machine with login disabled. Otherwise/mcpreturns401. - To connect from another machine, use the server address instead of
127.0.0.1. The token is then sent in plain text, so over the internet connect through an HTTPS proxy or an SSH tunnel. - Tools that trade on the exchange, start trading or irreversibly change data are marked as destructive
(
destructiveHint) — the client asks for confirmation before calling them: market orders, closing positions, cancelling orders, starting bots, saving and deleting strategies and keys, changing the config, shutting down and updating the program. - Reading state is marked as safe (
readOnlyHint).
Tools
| Settings | get_config, update_config, get_field_hints |
| Strategies | list_strategies, get_strategy, draft_strategy, save_strategy, copy_strategy, delete_strategy |
| Accounts | list_accounts, get_account, get_account_symbols, save_account, delete_account, get_account_info, get_balance_history, compact_balance_history |
| Bots | list_bots, get_balances, get_bot_bars, get_bot_state, pause_all_bots, play_all_bots, pause_bot, play_bot, send_chart_to_telegram, send_position_to_telegram |
| Positions and orders | list_positions, list_orders, market_order, close_position, close_all_positions, reduce_positions, cancel_order, cancel_account_orders, cancel_all_orders |
| System and logs | get_system_status, shutdown_program, update_program, get_log, get_errors, list_log_files, read_log_file |
| Tester | tester_status, get_tester_config, save_tester_config, tester_exchanges, tester_exchange_symbols, list_tester_settings, get_tester_settings, draft_tester_settings, save_tester_settings, copy_tester_settings, delete_tester_settings, get_tester_settings_folder, set_tester_settings_folder, tester_run_mining, tester_run_stress, tester_run_single, tester_run_snapshot, tester_download_data, tester_wizard_results, list_tester_files, read_tester_file, save_tester_file, delete_tester_file, tester_report_summaries, read_tester_report, tester_publish_files, tester_publish |
An API error is returned to the assistant as a tool error with code and text, for example
HTTP 404: {"success":false,"error":"Strategy not found"}. Very long responses are truncated to
200,000 characters. For long CSV files read_tester_file has the tail_lines and
contains parameters. To compare runs use tester_report_summaries, for details of a
single run — read_tester_report.
Research in the tester
The assistant can research a strategy on its own. The tester works on historical data and does not trade on the exchange. A typical flow:
get_field_hints— learn what the strategy settings and tester config fields mean, including theparameter_miningsyntax.draft_tester_settings,save_tester_settings— create settings for the exchange, pair and timeframe.save_tester_config— set the period, fees,parameter_miningand a newname_comment; enablereport.enable_json_report.tester_download_data— download candles and wait for completion intester_status.tester_run_singleortester_run_mining— test one combination or all of them: results intester_wizard_resultsor<name_comment>/reports_history.csv.read_tester_report— analyze a run: per-pair totals, months, trades.tester_report_summaries,tester_run_stress— compare the best variants and check their robustness (alsowalk_forwardin the config).
Example prompt for the assistant: "Find the zigzag length for BTCUSDT 1h on Bybit over the last three months. Compare the best variants by drawdown and check them with a stress test".
Response codes
| 200 | Success |
| 400 | Bad request: empty body, invalid JSON, required fields missing |
| 401 | No access: invalid api_token; cookie missing, expired or replaced by a new login; request without a token not from the same machine |
| 403 | Request from another website's page (Origin does not match the bot's address) |
| 404 | Not found |
| 409 | Conflict: tester or data download already running, name taken, required bot not running |
| 500 | Internal error or exchange error |
| 502 | External service rejected the request |
| 503 | The program is still starting |