Tektii just went live. We're shipping fixes daily — spot a bug? Let us know

Write Workflow

This workflow runs the full backtest loop: create a strategy, push your Docker image as a version, then configure, run, and read a backtest against it.

Overview

The write workflow follows these steps:

  1. Create a strategy - Set up a named container for your trading logic
  2. Prepare your Dockerfile - Ensure your strategy builds for the target platform
  3. Upload a version - Build and push your Docker image to the platform
  4. Write a scenario configuration - Describe the market data and window to test
  5. Run the backtest - Kick off the run with scenario create
  6. Read the results - Pull the headline metrics (return, Sharpe, drawdown)

Prerequisites

Before starting, ensure you have:

  • The Tektii CLI installed (Installation)
  • Your API key configured (Authentication)
  • Docker installed and running
  • A Dockerfile for your strategy

Need a strategy to upload? Your First Backtest has a complete paste-and-run strategy.py and Dockerfile, and Writing a Strategy covers the SDK in full — every callback, the order surface, position sizing, and history warm-up. Write the strategy to read the instrument and timeframe off the events it receives rather than hard-coding them; one uploaded image then runs against anything a scenario points it at.

Step 1: Create a Strategy

If you don't have a strategy yet, create one:

tektii strategy create --name "my-strategy"

This displays the newly created strategy as a field/value table:

✓ Strategy created successfully!

┌──────────────┬──────────────────────────────────────┐
│ Field        │ Value                                │
├──────────────┼──────────────────────────────────────┤
│ Strategy ID  │ a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d  │
│ Name         │ my-strategy                          │
│ Owner ID     │ user_...                              │
│ Created By   │ user_...                              │
│ Created At   │ 2024-01-15T10:30:00Z                  │
│ Updated At   │ 2024-01-15T10:30:00Z                  │
└──────────────┴──────────────────────────────────────┘

Note the strategy ID (a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d) - you'll need it for the next step.

If You Already Have a Strategy

List your existing strategies to find the ID:

tektii strategy list

Step 2: Prepare Your Dockerfile

Your strategy needs a Dockerfile so the platform can run it as a container.

Example Dockerfile

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .
CMD ["python", "strategy.py"]

Step 3: Upload a Version

Navigate to your strategy repository and run:

cd /path/to/my-strategy
tektii version upload a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d

The CLI will:

  1. Validate inputs (including that your Dockerfile exists)
  2. Auto-detect your Git SHA (or generate a timestamp fallback)
  3. Create a version entry in the API
  4. Build the Docker image
  5. Verify the built image targets linux/amd64
  6. Push the image to the registry

Custom Paths

If your Dockerfile isn't in the default location, specify custom paths:

tektii version upload a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d \
  --dockerfile ./docker/Dockerfile.prod \
  --context ./src

Flags

FlagDefaultDescription
--dockerfile <PATH>./DockerfilePath to your Dockerfile
--context <PATH>.Docker build context directory
--git-sha <SHA>Auto-detectedGit commit SHA for this version
--parent <VERSION_ID>-Parent version ID when branching from an existing version
--template <TEMPLATE>-Create the version from a platform template (ma-crossover, rsi-momentum) and skip the Docker build

Git SHA Detection

The CLI automatically detects your current Git commit SHA. If you're not in a Git repository, it generates a timestamp-based identifier like ts-1234567890.

To specify a SHA manually:

tektii version upload a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d --git-sha abc1234def

Version provenance & branching

Each version records two things that tie it back to your work:

  • Git SHA — the traceability link back to your source. Tektii stores the built image and the commit SHA, not your source code. To see what changed between two versions, run git diff <shaA> <shaB> in your own repository.
  • Parent version — lineage. --parent records which version this one descends from, organising your experiments as a branching tree. You can branch a new experiment from any version, not just the latest — point --parent at the version you want to fork from.

Apple Silicon (M1/M2/M3) Users

If you're on an Apple Silicon Mac, Docker builds natively target darwin/arm64, which the platform's scenario runner cannot run. You have two options:

  1. Open Docker Desktop
  2. Go to Settings > General
  3. Enable "Use Rosetta for x86/amd64 emulation"
  4. Restart Docker Desktop

Option 2: Use Docker Buildx

Create a buildx builder that can cross-compile:

# Create and use a buildx builder
docker buildx create --use

# Build with explicit platform
docker buildx build --platform linux/amd64 -t my-image .

Complete Example

Here's the full workflow from start to finish:

# Step 1: Create a strategy (if you don't have one)
tektii strategy create --name "momentum-v1"
# Note: Save the strategy ID from the output

# Step 2: Navigate to your strategy code
cd /path/to/momentum-strategy

# Step 3: Verify Dockerfile exists
ls Dockerfile

# Step 4: Upload the version
tektii version upload a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d

# The CLI will build and push your Docker image
# On success, you'll see the new version ID

Example Output

Validating inputs...
→ Detected version: abc1234
Creating version in API...
✓ Created version: b2c3d4e5-f6a7-4b2c-8d3e-4f5a6b7c8d9e
Connecting to Docker...
Building image ...
Verifying image platform...
Pushing image to ...

✓ Version uploaded successfully!

  Version ID: b2c3d4e5-f6a7-4b2c-8d3e-4f5a6b7c8d9e
  Git SHA: abc1234
  Image: ...

  Use this version ID when creating scenarios

Verify Your Upload

List versions for your strategy to confirm the upload:

tektii version list a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d

Get details for a specific version:

tektii version get a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d b2c3d4e5-f6a7-4b2c-8d3e-4f5a6b7c8d9e

Configure & run a backtest

Uploading a version doesn't run anything on its own — it just makes your strategy available. To actually test it, you run a backtest scenario: you describe what market data to feed the strategy and over what window, the platform replays that data through your image, and you read the results.

A config is a reusable saved preset and a scenario is a run of one against a strategy version — see config vs scenario in the commands reference. The steps below pass the config inline with scenario create; to save it for reuse, see Re-run a saved configuration.

Step 4: Write a scenario configuration

A scenario is defined by a JSON configuration file. tektii scenario create reads this file with --config:

{
  "strategyVersionId": "b2c3d4e5-f6a7-4b2c-8d3e-4f5a6b7c8d9e",
  "subscriptions": [
    { "instrument": "C:BTCUSD", "events": ["candle_1m"] }
  ],
  "startTime": "2024-01-01T00:00:00Z",
  "endTime": "2024-04-01T00:00:00Z",
  "initialCapital": 100000,
  "positionMode": "netting",
  "env": { "MA_SHORT": "20", "MA_LONG": "50" }
}

Each subscription pairs one instrument — a platform symbol like C:BTCUSD or F:EURUSD, from the Available Instruments catalog — with the events delivered to your strategy, such as candle_1m. The full field reference — every key, the valid events, the candle pattern grammar, and optional transaction costs — is Scenario Configuration.

Two plan caps apply to every run — how far back startTime can reach, and how long the window can span. Size the window against Plan Limits before you launch.

Step 5: Run the backtest

Pass the config to scenario create. Creating the scenario starts the run:

tektii scenario create a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d --config ./backtest-config.json

The command returns a scenario ID at QUEUED — submission is asynchronous — then the run moves through PENDING and RUNNING to a terminal state; note the success state is COMPLETE, not COMPLETED. See Scenario states for the full state machine.

Step 6: Read the results

Poll the scenario until it completes, then read its headline metrics with scenario get:

tektii scenario get a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d c3d4e5f6-a7b8-4c3d-9e4f-5a6b7c8d9e0f

That prints a summary table in your terminal. For a machine-readable object, add the global --output json flag:

tektii --output json scenario get a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d c3d4e5f6-a7b8-4c3d-9e4f-5a6b7c8d9e0f

For a completed scenario, the response carries the top-line performance fields:

{
  "data": {
    "scenarioId": "c3d4e5f6-a7b8-4c3d-9e4f-5a6b7c8d9e0f",
    "state": "COMPLETE",
    "totalReturn": 12.45,
    "sharpeRatio": 1.32,
    "maxDrawdownPct": 8.10,
    "totalTrades": 142,
    "winRatePct": 54.2
  }
}

totalReturn, maxDrawdownPct, and winRatePct are percentages (e.g. 12.45 = 12.45%). sharpeRatio and the other risk metrics appear only once a completed run has enough data to compute them. For a precise definition of each field — including what window Sharpe is computed over and how drawdown is measured — see the Results Reference.

You can also open the scenario in the web app to see the equity curve and metrics rendered as charts. For the downloadable result types — the full timeseries and the per-trade log, and every field they contain — continue to the Read Workflow and the Results Reference.

Strategy parameters: the env override map

A scenario config controls more than the market data and window. Your strategy parameters (indicator windows, stop-loss / take-profit, and so on) come from environment variables, and the image's ENV lines set the defaults — but they're not the only way to set them. The env field on a scenario config, and the per-run env you pass at launch, override the baked ENV for that run, so you can vary parameters against one image with no rebuild.

{
  "strategyVersionId": "b2c3d4e5-f6a7-4b2c-8d3e-4f5a6b7c8d9e",
  "subscriptions": [{ "instrument": "C:BTCUSD", "events": ["candle_1m"] }],
  "startTime": "2024-01-01T00:00:00Z",
  "endTime": "2024-04-01T00:00:00Z",
  "env": { "MA_SHORT": "20", "MA_LONG": "50" }
}

The per-run env wins over the baked ENV, so a parameter sweep is N configs (or N runs) against the same version, not N Docker builds.

Layering, lowest to highest precedence:

  1. The image's baked ENV (defaults).
  2. The saved config's env (per-config default override).
  3. The per-run env supplied at launch (wins).

To sweep a grid of parameter sets in one call, AI agents can use the MCP batch_run_scenarios tool with an env_grid — see Per-run env overrides & sweeps.

Re-run a saved configuration

Passing --config ./backtest-config.json to scenario create re-supplies the same file on every run. If you'll reuse a window, save the configuration once and run it later by its id — no file, and no re-typing the subscriptions, window, or capital.

Save the configuration

tektii config create --name "btc-q1-2024" --file ./backtest-config.json

This stores the config under your account and returns a config ID. Saved configs are user-scoped — list them again anytime with tektii config list.

Run a backtest from the saved id

Run the saved config against a strategy version with scenario run, passing the config ID as the first argument:

tektii scenario run d4e5f6a7-b8c9-4d4e-8f5a-6b7c8d9e0f1a --strategy-id a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d --version-id b2c3d4e5-f6a7-4b2c-8d3e-4f5a6b7c8d9e

The subscriptions, window, and capital all come from the saved config, so the only things you supply are which strategy and version to run it against. Like scenario create, this enqueues the run and returns a scenario ID at QUEUED — read it back with scenario get exactly as in Step 6.

scenario run is an alias of config run — identical arguments, identical behaviour; use whichever you remember.

Common Issues

Docker Not Running

Error: Docker not running

Solution: Start Docker Desktop or the Docker daemon.

Platform Mismatch

Error: Image platform mismatch (expected linux/amd64, got darwin/arm64)

Solution: See the Apple Silicon section above.

Git SHA Not Detected

Warning: Failed to detect git SHA, using timestamp fallback

This is not an error. If you're not in a Git repository, the CLI uses a timestamp-based identifier. To specify a SHA manually, use --git-sha.

Dockerfile Not Found

Error: Dockerfile not found at ./Dockerfile

Solution: Use --dockerfile to specify the correct path:

tektii version upload a1b2c3d4-e5f6-4a1b-9c2d-3e4f5a6b7c8d --dockerfile ./docker/Dockerfile

Next Steps