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

# Strategies

> Write a mandate and position limits, and an Itoflow agent runs a paper or live portfolio under them on a schedule. Version the strategy, run it on demand, and read each decision with its reasoning and trades. A person approves every live trade.

> [!TIP]
>
> **The easiest way: ask your AI assistant.** With [Itoflow MCP](https://docs.itoflow.ai/mcp/install.md) connected to Claude or Codex, paste:
>
> ```text theme={null}
> Use Itoflow to draft a paper strategy that holds 5 to 10 large US quality
> companies, with no position above 15%. Show me the full strategy before creating
> it, and create it paused.
> ```
>
> > [card] [Open in Claude](https://claude.ai/new?q=Use%20the%20Itoflow%20plugin%20\(https%3A%2F%2Fgithub.com%2Fitoflow%2Fskills\)%20for%20this.%20If%20it%20isn't%20installed%20yet%2C%20first%20tell%20me%20how%20to%20install%20it%20and%20sign%20in%20to%20Itoflow%2C%20and%20wait%20until%20I%20confirm.%20Then%3A%0A%0AUse%20Itoflow%20to%20draft%20a%20paper%20strategy%20that%20holds%205%20to%2010%20large%20US%20quality%20companies%2C%20with%20no%20position%20above%2015%25.%20Show%20me%20the%20full%20strategy%20before%20creating%20it%2C%20and%20create%20it%20paused.)
> >
> > Start this in Claude with the Itoflow plugin.
>
> > [card] [Open in ChatGPT](https://chatgpt.com/?q=Use%20the%20Itoflow%20plugin%20\(https%3A%2F%2Fgithub.com%2Fitoflow%2Fskills\)%20for%20this.%20If%20it%20isn't%20installed%20yet%2C%20first%20tell%20me%20how%20to%20install%20it%20and%20sign%20in%20to%20Itoflow%2C%20and%20wait%20until%20I%20confirm.%20Then%3A%0A%0AUse%20Itoflow%20to%20draft%20a%20paper%20strategy%20that%20holds%205%20to%2010%20large%20US%20quality%20companies%2C%20with%20no%20position%20above%2015%25.%20Show%20me%20the%20full%20strategy%20before%20creating%20it%2C%20and%20create%20it%20paused.)
> >
> > Start this in ChatGPT with the Itoflow plugin.
>
> Using another client? Copy the prompt with the button on the code block.
>
> No tokens or code needed. You can also do this in the [Itoflow app](https://app.itoflow.ai/strategies/new). The rest of this page covers the HTTP API.

A strategy runs a portfolio under a mandate you write. Each **run** (an execution) reads the mandate, researches, and records a **decision**: the trades it proposes. **Trades** record what then happened to each order. Keep execution, decision and trade IDs apart; they are different things.

```mermaid theme={null}
flowchart TD
  Draft[Mandate and constraints] --> Strategy[Versioned strategy]
  Strategy --> Run[Run]
  Run --> Decision[Decision]
  Decision --> Approval[Your approval, when required]
  Approval --> Trades[Trade outcomes]
```

Creating a strategy for an existing portfolio needs a known current value. If an open holding has no usable current price, creation returns `400 PORTFOLIO_VALUE_UNKNOWN` with a reason that names each such holding, and leaves the portfolio unlinked.

Public showcase holding weights use signed market value divided by net asset value (NAV), including cash. Holdings rank by absolute value and keep their signs. For example, a $1,000 portfolio with $600 and $300 holdings and $100 cash shows 60% and 30%. If value is unknown, each weight is `null` with `valuation_unavailable_reason`.

## Create a strategy

`POST /strategies` creates a paper strategy, which trades a simulated portfolio. You can also [create one in the app](https://app.itoflow.ai/strategies/new).

```json theme={null}
{
  "name": "Example research strategy",
  "strategyContent": "Research the listed companies and explain proposed changes before execution.",
  "constraints": {
    "min_position_pct": 0.02,
    "max_position_pct": 0.15,
    "max_positions": 5
  },
  "universe": ["AAPL.US", "MSFT.US"],
  "initialCapital": "10000",
  "currency": "USD",
  "rules": { "model_key": "luna" },
  "activateImmediately": false
}
```

| Field | Rules |
| - | - |
| `strategyContent` | Required. The mandate, in plain language. |
| `constraints` | Required: `min_position_pct` and `max_position_pct` as fractions of NAV (`0.02` = 2%), and `max_positions`. The position limits apply to a position's size, long or short. |
| `universe` or `allocationGuidance` | One is required: a list of `TICKER.EXCHANGE` symbols, or guidance on what to invest in. |
| `initialCapital`, `currency` | Starting cash for a new paper portfolio, as a decimal string. Between 1 and 1 billion US dollars, or the equivalent. Required without `portfolioId`. |
| `portfolioId` | Optional. Use an existing portfolio instead of a new one. |
| `rules` | Optional extra rules, including `model_key`. |
| `activateImmediately` | `false` creates the strategy paused. |

`max_position_pct` stays a ratio from `0.001` to `1`, and `min_cash_pct` stays from `0` to `1`. Margin and financing are out of scope. A target may hold more than 100% gross across names: thirteen longs at 10% each and three shorts at 10% each make a 130/30 book, and each position stays within its size limit. Trades are paid for from cash already held. A run's buys need cash above 110% of their value; a cover may also use what the run's long sales raise. A short sale's proceeds reach cash once it fills, so they pay for buys in later runs, not in the run that sells short. A paper book therefore builds a 130/30 position over several runs, and after each run its cash stays above a tenth of that run's buys.

`name` is required without `portfolioId`. Other optional fields are `description` and `sourceChatId`.

The `201` response includes `id`, `portfolioId`, `isActive`, `executionStatus`, and `effectiveConstraints` and `effectiveRules`. The effective fields include the defaults Itoflow filled in, so check them rather than assume an omitted control is off.

A portfolio watched by a fund-oversight monitor can't also have a strategy. Choosing one returns `409 PORTFOLIO_HAS_MONITOR`.

## Read strategies

* `GET /strategies` lists strategies you can see, which may include some you don't own.
* `GET /strategies/{id}` returns one strategy: mandate, whether you own it, portfolio, constraints, run state and version.
* `GET /strategies/public` lists the public showcase.
* `GET /strategies/eligible` lists strategies that can be linked to a broker. A strategy whose book or latest target holds a short is excluded because live short sales are not supported. A paper book whose current value is not known is also excluded. The response lists these books in `ineligibleStrategies`, with `strategyId`, `currentValue: null` and a `reason`. It never returns a partial sum as an eligible book’s value.

Only the owner can change a strategy.

## Change a mandate

`PUT /strategies/{id}` takes the fields you want to change. When you change the mandate, constraints, rules, universe or allocation guidance, also send `changeDescription`, or you get `400 CHANGE_DESC_REQUIRED`. Each change creates a new version; the response returns `versionId` and `versionNumber`.

> [!WARNING]
>
> **Editing cancels pending trades.** A new version cancels the strategy's pending trades, including approved live trades not yet sent to the broker. You can't edit a running strategy (`400 CANNOT_EDIT_RUNNING`) unless you change only the model; pause it first.

To avoid overwriting someone else's edit, send the `expectedVersion` you last read. If a newer version exists, the request fails; reload the strategy and decide again.

## Run a strategy and follow it

| Endpoint | What it does |
| - | - |
| `POST /strategies/{id}/control` | `action`: `pause`, `resume` or `deactivate`. Pausing or deactivating cancels unapproved trades; trades you already approved can still run. |
| `POST /strategies/{id}/execute` | Queues a run: `execution_type: "manual_rebalance"`, with optional `custom_message` and `trading_date` |
| `GET /strategies/{id}/active-execution` | The run in progress, if any |
| `GET /strategies/{id}/executions` | Run history |
| `GET /strategies/{id}/stream/{executionId}` | Live events from a run |
| `GET /strategies/{id}/executions/{executionId}/events` | Saved events from a run |
| `GET /strategies/{id}/decisions/{decisionId}/events` | Saved events for one decision |

`execute` returns `202` with `execution_id`, `strategy_id`, `status`, `estimated_duration_seconds` and `stream_url`. The run has been queued, nothing more, and a `202` is never a fill. Follow it, then check its decision and trades. Each request queues a new run, so if you lose the response, check `active-execution` before you try again.

For strategies on the legacy execution path, each failed automatic run makes
the trigger chain wait before it re-arms: 5 minutes, 30 minutes, 2 hours, then
24 hours for each later failure. A real decision from an automatic run clears
the count. The first failure on a new strategy version starts at one. Manual
runs, cancelled runs, blocked runs, completed runs with no decision, and skips leave the count unchanged.
Re-arming checks the trigger rules again; it does not promise a run at that time.
The failure wait also holds after a scheduler restart or a change to the trigger
rules. A new strategy version does not inherit the old version's wait.

On the legacy execution path, if the model provider rejects saved session
content, the run can retry in a fresh session within its three-attempt limit.
The agent keeps its saved workspace and states that it lost its prior session
context. Follow the run through its final decision or failure.

The live stream stays open through retries while the same run remains active,
including runs longer than 65 minutes. It sends the final status when the run
completes, fails or is cancelled. If the run is no longer marked active, the
normal stream timeout applies; check `active-execution` and the saved events.
A manual run queued behind an active run keeps its stream open while its own
task state is queued. It does not replace the active run's marker.

## Results

`/paper-trading/{strategyId}/status`, `/trades`, `/decisions`, `/approvals` and `/pending-trades` return a strategy's state and history.

`/paper-trading/summaries` lists **portfolios**, each with its trading mode, broker sync status and the strategy that manages it. `strategy` is `null` for a broker portfolio no strategy manages. A summary's `decisionType` says what the strategy decided, not whether an order filled.

A holding's `weight` is its signed value divided by the portfolio's net asset value. A book worth zero or less has no weights, so its `status` returns empty `holdings` and a `valuationError` with code `PORTFOLIO_VALUE_NOT_POSITIVE` and a message that gives the net asset value. Otherwise `valuationError` is `null`. Each summary's `status` follows the same rule. Both routes include available and reserved cash in net asset value: $100 stock, $100 available cash and \$100 reserved for a pending buy give a stock weight of 33.33%. The agent's history file and day-start returns count the cash a pending buy held at the time.

Before a paper-trading agent receives its input tables, preparation checks the
price, currency and exchange rate of every open holding. If any line cannot be
valued, the decision still runs. The files keep that line with a null value and
a reason naming the symbols. Portfolio value, cash weight, all holding weights
and returns that need the missing value remain null. Pending-trade projections
preserve these null weights. Trade sizing refuses when a stored open holding
cannot be valued; a missed live quote in the input files alone does not refuse
sizing. Historical reports and emails also check stored marks and show unknown
values when the evidence is unusable. An import price placeholder stays out of
the input tables, as it does from trade sizing.

The agent's history file uses a stored daily return only from the holdings
snapshot's own UTC date. A missing reading on that date gives a null daily
return. Cumulative return uses the latest reading at or before the snapshot;
portfolio value comes from that snapshot's holdings.

For holdings and trade approvals, see [Portfolios](https://docs.itoflow.ai/features/portfolios.md).

## Live strategies

`POST /strategies/live` creates a strategy for a live portfolio linked to a [broker connection](https://docs.itoflow.ai/features/brokers.md). It takes the same body as a paper strategy, but `portfolioId` must name a live portfolio. Its starting capital is the broker account's total value when you link it.

Every live trade needs your approval before Itoflow sends it to the broker. See [Approve trades](https://docs.itoflow.ai/features/portfolios.md#approve-trades).

## Models

Set `rules.model_key` to a fusion mode or a single model when you create or edit a strategy; edits without it keep the saved choice. New strategies without a choice use the plan's `default_mode` from `/pricing/model-access`. Each run pins both the main model and Guardian when it starts; retries keep those routes. A single choice uses that model for both agents. If you lose access to a paid choice, new runs stop with “Choose the Free model or upgrade” until you change the choice or upgrade. A connected ChatGPT subscription does not fund strategies. See [models and plans](https://docs.itoflow.ai/features/billing.md#models-and-plans).

For a walk-through, see [Run a strategy under a mandate](https://docs.itoflow.ai/use-cases/run-a-strategy.md). To design and test one first, see [Build and stress-test a strategy idea](https://docs.itoflow.ai/use-cases/stress-test-a-strategy-idea.md).

See the [strategy endpoint reference](https://docs.itoflow.ai/api-reference/coverage.md#strategies) for every field.


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