> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leeroo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The trading example: a harness and a task on it

> The trading harness shipped under examples/harnesses/trading, the task under examples/trading that runs on it, and what to read in the campaign afterwards: the task statement, the staged sessions, the verdicts.

Two directories in the repository: `examples/harnesses/trading`, a harness for systematic trading strategies, and `examples/trading`, a task on it. The task is deliberately small: three synthetic instruments with a trend in them, a 20/100 moving-average cross that scores a Sharpe of 0.14 out of sample (measured by us on the example's evaluator when the example was recorded), a brief that asks for 1.0. A faster cross or a volatility-targeted momentum signal gets there, so there is room, and every discipline of the domain has something to catch.

## The harness

```yaml examples/harnesses/trading/harness.yaml theme={null}
schema_version: 1
name: trading
version: 0.1.0
description: Research, implement, verify and deploy systematic trading strategies.

environment:
  python: requirements.txt

modules:
  setup:
    skills: [market-data]
    mcp_servers: [market-data]
    hooks: [session-brief, deny-web-fetch, protect-prepared]
  ideation:
    skills: [strategy-families, market-structure]
    hooks: [session-brief, deny-web-fetch, protect-prepared]
  implementation:
    skills: [backtesting, market-data, risk-limits, lookahead-scan]
    mcp_servers: [market-data]
    agents: [lookahead-auditor]
    hooks: [session-brief, deny-web-fetch, deny-web, protect-prepared, deny-snapshot, scan-writes, require-results]
  verification:
    skills: [backtesting, lookahead-scan]
    agents: [lookahead-auditor]
    hooks: [session-brief, deny-web-fetch, protect-prepared]
  feedback:
    skills: [risk-limits]
    agents: [risk-reviewer]
    hooks: [session-brief, deny-web-fetch, protect-prepared]
  deployment:
    skills: [market-data, paper-trading]
    mcp_servers: [market-data, broker]
    hooks: [session-brief, deny-web-fetch, protect-prepared, deny-snapshot]
```

| Kind | Name | What it is for |
| - | - | - |
| pages | `guardrails.md` and one per module except learning's twin | timing discipline (a signal at `t` earns from `t+1`), the risk line, where to look |
| skills | `backtesting`, `market-data`, `risk-limits`, `lookahead-scan`, `strategy-families`, `market-structure`, `paper-trading` | how to run a backtest, use the server, compute the risk line, scan a diff for look-ahead, what families exist, microstructure facts, the paper-trading runner |
| servers | `market-data` | `list_instruments`, `get_bars`, `get_calendar` from a pinned snapshot, and `snapshot` to build it from the task's data |
| | `broker` | a paper account: `get_account`, `place_order`; deployment only |
| delegates | `lookahead-auditor` | audits one attempt for look-ahead and leakage; the implementer and the verifier ask it |
| | `risk-reviewer` | reads an attempt's risk line and equity curve for the judge |
| hooks | `session-brief` | `SessionStart`: one context line pointing at the task statement |
| | `deny-web-fetch` | `PreToolUse` on `Bash`: denies `curl`, `wget`, `aria2c`; all prices come from the snapshot |
| | `deny-web` | `PreToolUse` on `WebSearch\|WebFetch`, implementation only: the evaluation window's future exists on the web; the engine's `implementation.web` switch is the boundary, the hook states the harness's rule with its reason (see [the web](https://docs.leeroo.com/docs/reference/harness.md#files)) |
| | `protect-prepared` | `PreToolUse` on the file tools: denies a file-tool write under `prepared/` (a shell write is not covered: a hook is a mistake catcher, not a boundary) |
| | `deny-snapshot` | `PreToolUse` on `mcp__market-data__snapshot`: the snapshot is built in setup only |
| | `scan-writes` | `PostToolUse` on the file tools: scans a written file for look-ahead patterns |
| | `require-results` | `Stop`: an implementation session does not end before `results/equity_curve.csv` and `results/trades.csv` exist |

`kapso harness check examples/harnesses/trading` prints `check ok (7 skills, 2 agents, 2 servers, 7 hooks)` and, on a machine without the harness's Python requirements, the `needs` lines for them.

## The task

```text examples/trading/kapso-brief.md theme={null}
Objective    Raise the strategy's out-of-sample Sharpe above 1.0 on the 2024
             window without breaking the signal contract: strategy.py keeps
             a signal(bars) function that returns the position to hold per
             bar, in [-1, 1], from that bar and the ones before it.
Measured by  kapso_evaluation/evaluate.py: the annualised Sharpe of the
             equal-weight portfolio over 2024 after 5 basis points per unit
             of turnover, with the risk line (max drawdown, annual turnover)
             printed beside it
Baseline     0.14 (the shipped 20/100 moving-average cross; max drawdown
             0.11, annual turnover 3.5)
Target       1.0
Rules
  - a signal at bar t uses only bars at or before t; the position decided at t earns from t+1
  - the 2024 bars are read by the evaluation alone; develop on 2021 to 2023
  - every price comes from the pinned snapshot the setup session builds; no live fetches
  - the evaluator is never modified
Budget       minutes=75 experiments=2
Harness      ../harnesses/trading
```

`generate.py` writes the bars from a seed, so the baseline is the same number on every machine: three instruments, business days from 2021 through 2024, each a random walk whose next return leans on the last twenty days' average by a weight of 0.35. The development years go under `data/`, the out-of-sample year under `private/`, which nothing copies into a workspace; the evaluator reads it through a pointer file beside itself. The evaluator imports `signal` from the workspace, shifts it by one bar, charges the cost on turnover, scores 2024 as an equal-weight portfolio, writes the two result files the `require-results` hook asks for, and prints the risk line then `sharpe: <value>` as its last line.

## Run it

```bash theme={null}
cd examples/trading
pip install numpy pandas pyarrow "mcp<2"
python generate.py
kapso harness check ../harnesses/trading
kapso build --brief kapso-brief.md --evaluation evaluation --data data --repo repo --output campaign --detach
kapso watch campaign --follow
```

The same build from Python:

```python examples/trading/run.py theme={null}
"""The trading example on its harness.

Run from this directory, after `python generate.py`; the campaign lands in campaign/."""
from kapso import Kapso, Brief

kapso = Kapso()
kapso.load_harness("../harnesses/trading")
solution = kapso.build(
    Brief.read("kapso-brief.md"),
    evaluation="evaluation", data="data", repo="repo", output="campaign",
)
print(solution.explain())
```

The brief's `Harness` line names the harness, so the command needs no `--harness`; `load_harness()` in the script is the same thing said in Python, and either wins over the line.

## What the campaign shows

1. The setup session runs first. It calls the `market-data` server's `snapshot` on `kapso_datasets/bars`, which lands under `prepared/market-data/` with a `MANIFEST.json` of hashes, and writes the domain statement: the instruments, the calendar, the window, what it pinned. `kapso_task.md` carries both.
2. Each experiment's implementation session has the backtesting and look-ahead skills, the `market-data` server and the auditor beside it; a write under `prepared/` is denied, a written signal is scanned, and the session cannot end before the result files exist. The stream under `.kapso/sessions/<branch>/stream.jsonl` shows each decision.
3. Each scored attempt is verified before it is judged: the verifier reads the diff and the evaluation output under `.kapso/verification/<branch>/`, runs the scan, asks the auditor where a pattern cannot decide, and writes `verdict.json`. A centred window or a future shift is a `void` with its file and line; the attempt stays on its branch and is never delivered.
4. The judge reads the verdict beside the evaluation and the risk reviewer's words beside the score.
5. `solution.explain()` ends with the harness's identity and the verdict on the delivered candidate.

Recorded result: a Sharpe of **1.93** out of sample on 2026-10-25, on a fresh machine with Claude Code, in 45 minutes and one experiment: the setup session pinned the snapshot, the implementer wrote a volatility-targeted momentum ensemble and asked the auditor, the verifier's verdict was valid, the judge called the target met. A second fresh machine scored 1.99 the same way.

## Change it

* **The harness.** Edit a page under `examples/harnesses/trading/instructions/`, bump `version`, run `check` again. The next build records the new hash; a resume of an older campaign refuses it by name.
* **The target.** The data's trend is worth a Sharpe of about 2 to a 20-day momentum signal; a target above 3 is not there.
* **The evaluator and the data.** `evaluation/evaluate.py` and `generate.py` are the task's own; change the metric in the evaluator and in `Measured by` together, change the trend weight and re-measure the baseline.

Related pages: [What a harness is](https://docs.leeroo.com/docs/harnesses.md) · [Use a harness](https://docs.leeroo.com/docs/harnesses/use.md) · [Write a harness](https://docs.leeroo.com/docs/harnesses/write.md) · [Harness reference](https://docs.leeroo.com/docs/reference/harness.md) · [Your first build](https://docs.leeroo.com/docs/first-build.md)

Kapso is an open-source framework by [Leeroo](https://leeroo.com) that builds software toward measurable goals through experiment campaigns. Source code: [github.com/Leeroo-AI/kapso](https://github.com/Leeroo-AI/kapso) · Install: `pip install leeroo-kapso` · Every page as plain text: [llms.txt](https://docs.leeroo.com/llms.txt).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.