- Research monitors watch a list of symbols, or whatever universe the mandate describes.
- Fund-oversight monitors watch one of your portfolios against a benchmark and peer funds, and check it against limits you set, such as tracking error or liquidity.
resource_type value
classifies the session projection in storage; it does not grant access or
change Monitor admission. Monitor reads and deletion use the Monitor’s owner.
Research reports use shared guidance on evidence, uncertainty, and quantitative
choices alongside the monitor mandate. This does not change the report format
or the fund-oversight workflow.
In the API, monitors live under /watchlists, their original name. To set one up with the agent’s help, start from New monitor in the app; the agent sets it up in chat.
When you set up a monitor in chat, you can ask for a model. The agent creates
the monitor with that choice. If you make no model choice, the usual default
applies. Model access checks still apply.
Create a research monitor
POST /watchlists creates a monitor. New monitors start paused, and creating one doesn’t run a report.
Schedules
recurrence.kind is daily, weekdays or weekly. A weekly schedule also needs a weekdays list, such as ["monday", "friday"]. Give local_time as HH:MM and timezone as an IANA name. Don’t convert to UTC: the time zone keeps the report at the same local time when clocks change.
Leave out recurrence, or send null, for a monitor you run by hand. When you edit a monitor, leaving out recurrence keeps the current schedule and sending null removes it.
Create a fund-oversight monitor
Setprofile to fund_oversight and describe the fund in profile_config. The subject must be a portfolio you own that no strategy manages; a portfolio can’t have both.
Fund-oversight creation and report execution depend on availability for your
account and the runtime assigned to the saved Monitor. Creating a Monitor does
not move an existing portfolio or Monitor to another runtime.
subject.name and subject.portfolio_id are required. The portfolio can hold one ETF or many securities:
- For a single ETF, reports look through to the fund’s dated holdings.
- Risk figures also measure funds held beside other holdings through their dated holdings at each line’s signed weight, down to three funds deep, and count the cash inside them as the book’s cash; holdings lists, concentration and liquidity keep the fund line.
- For several securities, reports use the portfolio’s own dated positions. Changes and risk change use saved books at or before the requested dates.
- An ETF inside a multi-security portfolio counts as one holding.
index_symbol. A price index such as GSPC.INDX leaves dividends out; a fund that tracks it, such as SPY.US, includes them. For holdings comparisons, name a fund that holds the index in basket_symbol. If you leave the basket out and index_symbol is itself a fund, Itoflow uses that fund’s holdings. A plain index with no basket is compared by returns only.
The comparator slots are benchmark and peers. Realised beta uses the benchmark’s
price series: index_symbol when set, otherwise basket_symbol. Forecast beta
uses its holdings book. They have separate metric keys,
risk.realised_beta.benchmark and risk.beta.benchmark. With no benchmark, the
report has no benchmark beta row and its receipt says: “This Monitor names no
benchmark, so beta is not configured.” Peers keep their forecast beta rows.
Missing benchmark prices are a data gap.
Removing the separate beta reference preserves tracking-error history when the
subject and comparator books stay the same. Changing the subject or benchmark
starts new history. Earlier realised-beta values under the retired metric key
are not carried into risk.realised_beta.benchmark. Detail, list and version
history omit the retired comparators.beta_reference setting without changing
stored versions. Scheduled runs and runs pinned to earlier settings ignore that
key and measure beta against the benchmark. The reporting agent’s configuration
brief also omits that comparator setting, while preserving other settings and
custom context. Sending a configuration with the
retired key is rejected. A metadata-only edit succeeds and omits it from the new
version’s inherited settings; earlier versions remain unchanged.
Each section carries one status:
With no benchmark or peer, attribution, factor return, bets, forecast quality,
drivers and risk change are not set up. With no limits, compliance is not set up.
Risk, exposures and sizing keep their subject figures.
Those comparator sections and compliance stay not set up even when the subject book is unusable;
the receipt records the subject failure and subject-only sections report the data gap.
Compliance rules compare cash, above-5% issuer bucket, single issuer and relative
weights against configured limits. The illiquid-days cutoff enables a share
measurement but adds no rule or ceiling. A tracking-error budget, row threshold
overrides or liquidity tuning alone do not set up compliance.
Named peers whose books could not be read remain data gaps. The panel lists
sections that are not set up apart from failed sections, with their reasons and
without section numbers. The receipt names them in
sections_not_configured;
older saved reports may omit that list.
Peers. Name each peer fund by symbol, up to 10. Itoflow needs each peer’s holdings, so a symbol with price history alone won’t work. Holdings dated more than 183 days before the report date don’t count. A fund that closed or changed its ticker stops publishing them, so the run names the date of its last holdings; use the fund’s current ticker or another fund.
Fund books. Itoflow reads a fund’s holdings from one market data provider for its market. When that provider states no holdings for a fund, Itoflow has no book for it and the run reports the book as missing. When a stored book has gone stale, the run fetches it again; if that fails, it uses the stored book and warns with the date it went stale. Sector or region weights alone don’t stand in for holdings. When Itoflow can’t confirm the currency of a fund’s holdings values, as for some funds listed outside the US, the report shows those values without a currency.
Itoflow looks for the source’s valuation session within each listing currency’s
last five sessions, all on or before the holdings date. At least three distinct
securities must support a match: a median ratio within 0.5% of one and more than
half the rows individually within 2%. A tie within 0.1 percentage point uses the
later session and is reported as ambiguous. A matched count that disagrees with
its own market value by more than 2% becomes unverified; the holding keeps its
stated weight. The receipt gives affected count
and weight with share count disagrees with market value in the book’s currency.
The foreign-currency group check still catches groups clustered at their rate.
When no session matches, the receipt says the source’s valuation date was not
found. The 25% gross-error filter then rejects large disagreements, while
passing counts remain unverified. Missing comparison data leaves existing
behavior unchanged. Groups below three rows and currencies within about 5% of
parity remain gaps in the group check. Matching a session never changes the
book-date close used to value holdings and test weights; marked price breaks
make a row fall back rather than verify an earlier count across that break.
A fund book keeps the weights its source states. Itoflow tests them against the
book’s share counts and closes. When the two are more than 10% apart, the book
stays in use on its stated weights, and the receipt says share counts disagree
with stated weights by X%; stated weights kept. A source can state the right
weights beside wrong share counts, so Itoflow never rebuilds weights from the
counts, and uses them for nothing else either: no weight move in that book is
split into trade and price drift from them. Results from earlier runs may still
say weights: rebuilt_from_shares and carry a total_basis; Itoflow no longer
writes either. A book’s total is the one its source states; a book whose counts
agree with its weights can also use the sum of its valued holdings. Each held
fund’s dated note also appears in the parent’s receipt, prefixed by its symbol
and holdings date.
Mandate vs. limits. Put numeric limits in thresholds. Put objectives, exceptions and report preferences in the mandate. Don’t copy the portfolio’s current value into the mandate; it goes stale. The named fields reject unknown keys; put anything else under custom.
For a US-listed fund, the first report can already show what changed since the last quarterly SEC filing (Form N-PORT). Itoflow uses each filing only from the day the SEC accepted it. It doesn’t yet use a filing that holds short positions, because the filing data it reads doesn’t state the fund’s net assets.
Limits
Which comparator.
relative_weight and tracking_error_budget apply to one comparator, named in thresholds.comparator: "benchmark" or a peer fund’s symbol. It defaults to the benchmark. Reports still show every comparator.
Warnings. By default a limit warns at warning_fraction of its value. To set one limit’s warning level, add it under thresholds.warnings in the limit’s own unit. {"tracking_error_budget": 8, "warnings": {"tracking_error_budget": 6}} warns at 6% and breaches above 8%. The warning must be inside the limit.
Single report rows. thresholds.metrics overrides one row of the report, keyed by the metric_key shown in the latest report. The monitor needs at least one report first. An override stays saved even if a later report drops that row.
The report brief calls compliance not configured when there are no comparison
rules, not assessable when rules are configured but none can be fully assessed,
and assessed when at least one rule can. Measurements stay visible in each state.
Liquidity. By default Itoflow assumes you can sell 10% of each holding’s average daily traded value, averaged over the last 20 trading days. Days with zero volume count; missing volume is never filled in. Set liquidity.participation and liquidity.adtv_window_months to change this. Reports show the rate and window they used.
If Itoflow can’t read a holding’s volume history after one retry, the report names that holding as a gap, with its weight, and still measures every other holding.
Fund size scenarios. aum_scenarios re-runs the sell-down at other fund sizes. Give up to 50 sizes above zero. Two sizes equal to six significant figures count as one, so [500, 500.0000001] is rejected and [500, 500.001] is accepted.
The API returns 400 for a comparator the monitor doesn’t have, a warning for a limit that isn’t set or a warning outside its limit, and a metric_key the latest report doesn’t contain.
Read, edit, copy and delete
Every saved change creates a new version and keeps the old one. Reports record which version they used. Being able to read a monitor doesn’t let you edit it; fork it instead.
Pause a monitor before you edit it. Editing an enabled monitor returns
400 CANNOT_EDIT_RUNNING, unless you change only the model.
Other 409 codes: DUPLICATE_NAME when you already have a monitor with that name, and PORTFOLIO_HAS_STRATEGY when a fund-oversight subject portfolio has a strategy.
You can’t turn a research monitor into a fund-oversight monitor. Create a new one.
If a read returns 503 with code: "MONITOR_LIFECYCLE_UNAVAILABLE", Itoflow couldn’t confirm whether the monitor is paused or running. Retry; Itoflow doesn’t fall back to a possibly stale status.
DELETE stops new work and returns 204 once everything is removed. If cleanup takes longer, it returns 202 with code: "MONITOR_DELETE_PENDING". Send the same DELETE again to check. Meanwhile, reads return 404 and edits return MONITOR_DELETE_PENDING.
While Itoflow moves a monitor to its new runtime, the monitor reads with runtime_move_pending: true. Edits, runs, schedule changes and DELETE then return 409 with code: "MONITOR_RUNTIME_MOVE_PENDING". Reads and reports stay available. Try again in a few minutes; the move keeps the monitor’s ID, versions and reports.
Run reports
During an update, manual runs may return503. Retry in a few minutes.
If a previous run is still finishing, a manual request may be refused. Wait
briefly and retry. A refused request does not create another run in history.
Cloudflare monitor reports can recover across repeated restarts while their
start or latest resume is within 90 minutes. Repeated crashes on the same
software version can still stop a run; check its status and saved report before
starting it again.
Calculated inputs for Cloudflare monitors
When the Cloudflare runtime is enabled for your monitor, each run prepares its calculated inputs before writing the report. A research monitor with symbols saves a dated analytics snapshot. A monitor without fixed symbols follows its mandate without a symbol snapshot. Fund oversight prepares its books, risk and other figures, then uses those saved figures in the report. The saved runtime owner controls later runs; a creation setting does not change that assignment. A research snapshot’sas_of shows the latest price date used by the calculation.
It can precede the report date, such as when a run starts before the market closes.
That difference does not prevent the run from saving its analytics or publishing
its report.
If a run cannot prepare valid inputs, it can fail with a reason rather than
publish unsupported figures. Partial data remains an explicit gap in the report.
To get the same symbol analytics without a monitor, for any 1 to 12 symbols,
use GET /symbols/analytics. It saves
nothing to a monitor.
The research analytics panel loads saved snapshots separately from report text.
Creating or editing a monitor does not promise an immediate snapshot. Until a
run saves one, the panel says no snapshot exists. After an edit, it labels a
known earlier snapshot while waiting for new results. If a refresh fails, it
keeps the last saved snapshot and shows a refresh warning. Without saved data,
a failed read shows an unavailable state. A monitor without fixed symbols has
no symbol analytics; fund oversight keeps its figures in the report.
Saved charts and tables
Cloudflare reports save their rendered chart figures and table snapshots with each execution, using the same output preparation and renderer as Chat. Reopening a report shows its saved data even after another run changes the workspace files. The optionaldataframe_snapshots field on a report response
holds those saved table rows and their paging and truncation metadata. Older
reports without embedded figures or table snapshots remain unchanged.
Browse complete tables
When a report offers Show all, open it to browse the complete table inside its existing section, 25 rows per page. The page arrows move through the list. Short lists need no page controls. Search by a recorded name or ticker, set a minimum value with Filter, or select a column heading to sort. A figure sorts largest first and a name A to Z; select the heading again to reverse it. These apply to the whole list before the report selects a page. Changing the search, filter, or sort returns to the first page. A missing value reads Not known. Each table states its date, comparator, computed period and weight basis above its rows, and each figure column names its unit. Where a column has a definition, the information mark beside its heading shows it. A cell shows two decimals; hold the pointer over it for the exact stored value. Download exports every matching row, including rows beyond the visible page or the section’s cut. The file keeps the search, filter, order, dates, comparator, units, and stored precision. Show top N or Show summary returns to the section’s own cut. Attribution shows the best and worst contributors side by side. Each side is ranked over every recorded name by the sign of the measure, so a short side is never filled with names of the other sign. The complete contributor table opens below them.Save how a report reads
Opening the full list, searching and paging never save anything. The cut (Top 10, Top 20, …, All rows), the order, a filter, the computed period, and Table or Chart are the section’s view. Changing one shows the result at once and raises Unsaved changes at the bottom of the report. Save view asks where the change applies: This report and future reports, This report only, or Future reports only. A save for this report keeps the original publication intact. A save for future reports applies when the next run starts and does not alter a run already in progress. Saving from an earlier report changes only what you changed there; newer settings for other sections stay as they are. Discard drops the unsaved change. After a save the report offers Undo. Report view lists the saved changes and can preview or restore the report’s published view. Each saved change also appears as a short line in the monitor conversation.Ask the monitor about a report
Where a report offers its own chat, ask about the recorded figures or request a view change there. Chat uses the same settings as the controls. A new table or chart must pass a query against that report’s data before it can be saved. A message sent while a report is being generated waits until that work finishes; browsing and the view controls stay available. On a wide screen the chat keeps its own column beside the report and can be hidden; on a narrow one, use the Report and Chat tabs. These controls need the source kept for that report. When the source or a table’s rows are unavailable, the published report remains readable; the app does not substitute a newer report’s data.Enable or pause
POST /watchlists/{id}/control with {"action": "enable"} or {"action": "disable"}.
- An enabled monitor with a schedule runs on that schedule. Add the schedule before you enable it.
- Some monitors can’t be enabled without a schedule and return
409 WATCHLIST_RECURRENCE_REQUIRED. You can still run their reports by hand while they’re paused. - If the response contains
report_scheduling: "unavailable", Itoflow couldn’t set up the schedule, even if other changes saved. Try again. - A failed enable returns
503and leaves the monitor paused. It’s safe to retry.
Run a report now
POST /watchlists/{id}/reports/run queues a report. You can send a one-off instruction of 1–500 characters:
custom_message_applied: false. Cloudflare Monitors apply nonempty instructions only to a newly admitted manual execution. Omit the field when no override is intended; Monitor Chat also treats a blank tool instruction as no override. The standing mandate, version and later runs stay unchanged.
The 202 response:
If Itoflow can’t confirm the run in time, the response is only
{ "status": "pending" }. The run may still start. Check GET /watchlists/{id}/active-execution before you try again.
report_date is set when the run starts, in the schedule’s time zone, or UTC for a monitor without a schedule. You can’t choose it.
Read reports
Despite its name,
{reportId} takes the execution_id from the history list, not the report_id field.
For each live Cloudflare Monitor, each local date due while running ends in one
report or one failed run in history. An outage may delay the update. The schedule
history keeps due dates even if the Worker misses an alarm or restarts. A row
still open at its next scheduled time becomes a visible failure. Manual runs have no fixed deadline. Itoflow retries recording an answer or failure up to three times. A manual run may stay open if those writes keep failing. A run that never started gets a visible failure after a short wait; a run still working stays open. If another run
is active, the new date fails with a reason naming that run; the older run
continues. Select a failed execution in history to read error_message. If an ended run is still finishing, Run now asks you to try again shortly.
Pausing stops future scheduled runs. A run or repair already in progress finishes and publishes on its original row, including when its answer is still being saved after computation finishes; its deadline still applies. A due run that has not started becomes a visible failure. Resuming starts
a new running interval; dates in the paused gap do not run. A timezone edit
changes future dates and keeps each already-due date in its original timezone.
A run uses the configuration current when it starts. If its subject portfolio
or profile is no longer valid, a scheduled date records a failure with the
reason; Run now returns the refusal directly. Completed reports cannot change.
Deleting a Monitor removes its runs and reports and ends its date obligations.
While a run is in progress, GET /watchlists/{id}/executions/{executionId}/results returns each result the run has shown so far, oldest first: symbol cards, symbol analytics or a risk engine panel. Each result has a view with its status (ok, partial or failed), its as_of date (null when the result failed) and, for a partial or failed result, a reason, and a component with the data, which is null when the result failed. Take executionId from active-execution. A run’s results are only ever added, so when you poll, pass after with the number of results you already have, and the response holds the new ones; keep each result by its view.result_id, because one can come again when the server skips a result it cannot read. Anything but a whole number from 0 to 999999 returns 400. A run that shows no results returns an empty list, and a run of another Monitor returns 404.
Results so far are rolling out: until they are turned on for your account, this route returns 404.
view_settings: true in its report record; a report without them has no such field, and its page asks for no settings.
A run’s status is queued, running, completed, failed or superseded. superseded marks a run that a newer one replaced. reports/latest returns the latest completed report, so it doesn’t tell you whether a newer run has finished.
When the engine refuses invalid input, the failed run’s error_message explains
what to change. A portfolio that holds only cash has no securities to monitor;
add a holding and run it again.
By default, a report tells you what matters now, including matters still open, and what changed since the last report sent to you. Failed and superseded runs don’t count as sent. Your mandate decides what a report covers and how it reads: for example, ask for a report that stands on its own if you read weekly, or for only the changes if you read every report.
What a fund-oversight report contains
Each name’s sector comes from its industry group in the published factor model used by the run. The report maps that group to its GICS sector, so the sector split uses the model’s classification. This also applies in FMP-routed markets, where the model derives the group from the provider’s industry through a checked-in table. A name without a published group keeps its stated sector. After coverage completes, one batch for the subject and comparators reads the same publication pinned for measurement, no later than the report date. Older held snapshot dates do not constrain the model read. The report opens with a summary and numbered findings (A1, A2 and so on), open issues and the most severe first. It then answers three questions: “How am I doing?”, “What is going on?” and “Are my decisions good?”. Each has numbered sections (1.1, 1.2 and so on) showing up to three key figures. The report starts from Itoflow’s risk engine’s figures. The agent explains them, and may correct a figure or add its own from further analysis. Names asked for coverage stay in the fitting universe permanently, including names a request could not cover. Each daily fit tries them again. Later runs report known uncovered names with the pinned fit’s reason and do not wait for them. When the engine asks for new names missing factor coverage, it waits at most 60 seconds for a worker to claim the request. A final status check confirms the result before it stops waiting. A claimed request, or one whose claim state the service cannot report, retains the ten-minute total cap. Measurement continues with any remaining names unscored. If a risk run’s full figures exceed the storage limit, the run keeps its result and panel, gives no artifact path, and states the size and limit; exact figures then come from the view and panel only. If the engine has evidence a figure is wrong, the report leaves out that figure and any conclusion that depends on it, rather than guessing. A risk comparison that needs a covariance repair carries a warning and is marked incomplete. If the covariance total is not finite, the output warns that it shows factor-only risk and leaves the returns weight unmeasured; a negative total makes risk unavailable. An analysis that couldn’t run appears only when you can fix the cause, for example by setting a participation rate. Books used lists the dated holdings sources behind the report. For attribution, the engine uses the latest holdings book dated on or before that period’s start, for both the subject and each comparator. It never uses a later book to fill a gap. The start is the last session close on or before the prior calendar period end, using the engine’s exchange calendar. A five-session window starts at the close before those five sessions. The engine publishes that start and carries the selected weights forward using price moves, assuming no intervening trades. There is no calendar-day distance limit for a start book. If no book exists on or before the requested start, that period is not covered. The report section and tool reply sayHistory starts <date>. The engine keeps
the requested period and marks the gap partial or unavailable; it never silently
shortens the period.
For a saved portfolio, the opening snapshot chooses whether to look through
a fund. A mixed opening keeps its own lines, even if today’s portfolio holds
only one fund. When the opening holds one fund plus cash, its constituent book
passes the same weight check as the other books. It keeps its stated weights;
a rejected book withholds that opening.
Accepted constituent weights first move from their own date to the saved edit using prices. The saved
fund/cash split applies on that edit date; the combined book then moves to the
period start. Missing prices for the first move withhold the figures.
Since inception starts at the subject’s first available price. The engine resolves
that date before reading opening books, even when they fall outside recent
history. A missing opening book keeps that full period uncovered. If factor
returns, opening exposures or the fund’s ending close are also missing, the
reason names both gaps. A resolved period start still gets its book-coverage
check when prices cannot measure the period; its figures stay withheld.
A filing can supply weights once the regulator has accepted it by the report
date. A replay uses its own report date as that knowledge cutoff. Opening
book row kinds and diagnostics use that cutoff, including corrections known
after the holdings date but before the report date. Later corrections stay out.
Both start and end reads exclude holdings dated after the report date, even if a later
knowledge cutoff is supplied. Each attributed period names both books’ dates,
the period start, and any forward carry in calendar days, beside the assumption
of no intervening trades. For example: “Attribution is estimated using holdings
dated 29 September, rolled forward 1 calendar day to 30 September assuming no
intervening trades.” In the period values, subject_weights_roll_direction
and comparator_weights_roll_direction are forward when weights move, or
null when the book is dated at the start.
For example, February 2026 ends on Saturday: a March month-to-date period
starts at Friday 27 February’s close. A book dated 27 February has zero roll.
A listed fund’s ending close comes from its own price history; current
constituent prices cannot advance it. Only unlisted portfolios use constituent
closes. A missing listing history withholds the period.
Session-count periods end at the subject’s last available close. A five-session
period reported on Monday 9 November 2026, with prices only through Friday
6 November, starts at Friday 30 October’s close. The start books and published
dates use that same window. A window without enough price history is withheld;
it is never published as a shorter period under the five-session label.
The risk-change section’s prior-model book keeps its ordinary on-or-before
read, including its existing current-book freshness rule.
Saved engine reports retain their published contract. Readers accept versions
1 and 2 permanently without rewriting saved reports. Version 2 attribution figures and numeric
details state their measure, actual common dates, comparator and basis_id.
The embedded basis records the calculation definition, opening books, dated
book path and price coverage, including reconstruction assumptions. A citation
retains this context with its figure. A daily basis can also carry a compact
gap summary for each side: distinct dated gap days, affected names, and the
sum of their absolute period-average weights in percent. Unknown weight is
null with a reason. Deploy these readers in every production unit before
the writer starts emitting version 2.
For attribution, the engine uses the latest holdings book dated on or before
that period’s start, for both the subject and each comparator. It never uses a
later book to fill a gap. The start is the last session close on or before the
prior calendar period end, using the engine’s exchange calendar. A five-session
window starts at the close before those five sessions. The engine publishes
that start and carries the selected weights forward using price moves, assuming
no intervening trades. There is no calendar-day distance limit for a start book.
If no book exists on or before the requested start, that period is not covered.
The report section and tool reply say History starts <date>. The engine keeps
the requested period and marks the gap partial or unavailable; it never silently
shortens the period.
Since inception starts at the subject’s first available price. The engine resolves
that date before reading opening books, even when they fall outside recent
history. A missing opening book keeps that full period uncovered. If factor
returns, opening exposures or the fund’s ending close are also missing, the
reason names both gaps. A resolved period start still gets its book-coverage
check when prices cannot measure the period; its figures stay withheld.
A filing can supply weights once the regulator has accepted it by the report
date. A replay uses its own report date as that knowledge cutoff. Opening
book row kinds and diagnostics use that cutoff, including corrections known
after the holdings date but before the report date. Later corrections stay out.
Both start and end reads exclude holdings dated after the report date, even if a later
knowledge cutoff is supplied. Each attributed period names both books’ dates,
the period start, and any forward carry in calendar days, beside the assumption
of no intervening trades. For example: “Attribution is estimated using holdings
dated 29 September, rolled forward 1 calendar day to 30 September assuming no
intervening trades.” In the period values, subject_weights_roll_direction
and comparator_weights_roll_direction are forward when weights move, or
null when the book is dated at the start.
For example, February 2026 ends on Saturday: a March month-to-date period
starts at Friday 27 February’s close. A book dated 27 February has zero roll.
A listed fund’s ending close comes from its own price history; current
constituent prices cannot advance it. Only unlisted portfolios use constituent
closes. A missing listing history withholds the period.
Session-count periods end at the subject’s last available close. A five-session
period reported on Monday 9 November 2026, with prices only through Friday
6 November, starts at Friday 30 October’s close. The start books and published
dates use that same window. A window without enough price history is withheld;
it is never published as a shorter period under the five-session label.
The risk-change section’s prior-model book keeps its ordinary on-or-before
read, including its existing current-book freshness rule.
Weight your portfolio or upload leaves unlisted is cash and stays outside
gross exposure. Weight a provider or filing leaves unlisted
is unknown. It counts in gross by its size, stays uncovered, and the return
figures hold it at zero return under Not listed by the source. If a book’s
net assets reach zero or below during a price drift, figures that need that
drift read not known, with the book and day in the reason.
A line the engine cannot value keeps its stated weight, stays uncovered, and
earns zero return. It stays in gross exposure and never becomes cash. Cash
sits outside gross in model, classification, valuation and liquidity coverage.
Cash remains available in liquidation proceeds, and cash-limit checks include
owner implied cash. A book of cash alone earns zero return. Attribution counts
measured security returns separately from lines held at an assumed zero return.
Cash-marked money-market funds and filing short-term investment vehicles count
as cash, earn zero return, and stay outside gross and security price coverage.
Their labels say they are money-market funds counted as cash. Cash-and-equivalents
lines are cash too. A line named for a currency, by its code or its name, is
cash only when ISO 4217 lists that currency as money. A stated cash currency
code, including a cash identifier such as CASHUSD00, can establish its
currency; reserve and accounting units, test codes, fund units and metals
cannot. A line named for a metal holds the metal, not cash.
Untagged cash can take the fund’s currency only with independent dated net
assets: within one trading session, the book must agree within 0.05% with all
untagged cash included and miss by more than 0.05% without it. On any read for a past date, cash proved by a net-assets figure dated after
that date is not known. Multiple untagged
cash rows are tested together. A failed proof states both percentage
gaps; absent evidence leaves the gaps unknown. The current filing feed omits
the needed net-assets figure, so its cash retains unknown currency unless the
row states it. Provider books reuse the dated assets figure and currency from
their existing profile reply. Missing currency or an unavailable calendar
leaves the proof incomplete; no extra provider request fills the gap. Refreshes
can update stored row kinds; existing saved reports retain their original data.
Attribution coverage includes weight a third-party source leaves unlisted in
eligible gross, with a separate gap from listed holdings that have no usable prices.
Across periods, attribution states the dated book with the largest combined gap
and that book’s split between unlisted and unpriced weight.
A holding whose stored specific variance is above the bound the model caps
it at stays outside the risk figures, with its signed weight and
specific_risk_out_of_range in coverage. A name an earlier
model run recorded as prices_not_usable carries that reason, and its older model
rows are not carried forward. The model trusts prices as they arrive and leaves no
name out for the size of a move.
The factor split needs the model’s daily returns to reach the period’s last
priced day. If they stop earlier, the report leaves that period unsplit and
states both dates; the factors’ share of the gap is not known.
Liquidity keeps unvalued and unlisted weight in its gap receipt even when volume
reads succeed, and applies the same 0.5% materiality floor as exposures and compliance.
Every section uses the same clock. A report reads today’s data when its date
is today or later in the report’s own timezone. Today’s listing directory
can explain retirement only on such a report.
On today’s data, the engine keeps a retired holding’s observed closes through
its last close in the loaded history. It states no value after that date,
even when the requested window ends later or other holdings have newer closes.
If a price drift reaches beyond that close, the holding keeps its book weight
and the receipt names the last close and the unknown later value.
A missing provider link or stated currency still prevents a
price read, and the receipt keeps that reason. Trading listings take priority
when a provider also lists the same code as retired.
If a Monitor or risk run leaves a holding outside the factor model because
its prices stop short, the shared price history can name retirement on
today’s data. The line gives the last observed close date when known.
Without shared price history, it keeps the general price-coverage reason
and reads no directory to infer a cause. The holding stays unmodelled.
On an earlier report date, prices use the ordinary tail check and close
carry for every listing. No later-history probe runs. A series ending more
than five weekdays early gets a price-gap receipt, including in a one-holding
book. The cause stays unknown. Currency lookup still uses stated currencies
from trading and retired listings on every date.
A holding with a book weight that is not a finite number stays outside model
coverage, even when the model covers its listing. Its coverage row has
weight: null and reason code invalid_book_weight: “Its book weight is not
a valid number, so its risk is not known.”
On today’s data, liquidity leaves out a retired line unless it traded on the
report date itself, even on a weekend or holiday. The receipt names retirement
and the last observed trade date when known. A retired comparator has no
realised beta on today’s data. If the retired directory cannot be read, the
receipt names the affected venue and the count of listings with unknown status.
On a replay, liquidity uses the observed readings without today’s listing
status or retirement wording. Realised beta uses the paired returns like any
comparator. Prices, drift, factor coverage, beta and liquidity all follow the
same report-date rule.
A portfolio without a dated return series keeps its forecast risk and beta.
It publishes no realised-beta row, and the receipt explains the method limit
without making risk partial. Missing benchmark prices for a listed-fund subject
remain a data gap.
Company listings use the company legal entity identifier mapped from their
international securities identifier, then the provider key. Provider identifiers
count only when their classification date is on or before the report date.
A unique shared filer number joins a filer-only line to its legal entity
identifier. Conflicting links stay unresolved. Equal registered keys group
listings into one issuer; funds have no issuer key.
The receipt names lines with no key and both sides of a possible unbridged
filer-versus-legal-entity split. It states their book and total absolute weight,
before longs and shorts can cancel. A settled position is an equal-key group
with no named line. Unresolved weight includes every line in other groups,
plus unlisted source weight.
On one side, the largest issuer’s upper bound is the largest settled position
plus unresolved weight. The above-5% bucket’s upper bound sums the settled
positions above 5%, then the settled positions nearest 5%,
taken while their summed gaps to 5% stay below the unresolved weight: each
position it lifts uses up its own gap; it adds unresolved weight only if a
settled issuer can exceed 5% or the unresolved weight alone exceeds 5%. When bounds
differ, the report shows at least and the upper bound beside it. It reports
a breach only when the lower bound reaches the owner’s limit, within only when
the upper bound stays below it, and otherwise leaves the verdict not known.
Longs and shorts with unresolved weight have no issuer verdict. Trim plans need
zero unresolved weight. Issuers are legal entities; a consolidated group limit
needs dated parent links.
For example, settled positions of 6% and 3% and an unresolved 2% line give a
largest-issuer range of 6% to 8%: within a 10% limit, unknown against 7%.
The country split uses the listing venue’s country when the company states none;
its receipt states the weight that used this fallback for each book.
Funds, including exchange-traded funds, mutual funds and UCITS, receive no
issuer key because an umbrella identifier can name several funds. Company
holdings in a fund’s look-through book use the same company-key rule. The
first map covers held-line identifiers from 3 November 2026; identifiers outside
that snapshot use the stated provider key or count alone. Unlisted source
weight remains a separate coverage gap.
Valuation compares long names with long names and short names with short names
within each sector.
A derivative whose figure has no proven contra offset keeps the book usable.
Every row remains, with stated weights labelled % of the provider’s total
in the book note. The derivative’s exposure and direction are not known; a
negative figure is never treated as a short. The receipt’s
exposure_unknown_reason explains the gap beside total_note.
Exposure-dependent book totals are not known: long and short sides, gross and
net exposure, leverage, factor and risk totals, and book-level liquidity
aggregates. Gross has a lower bound from the other rows’ sizes. Risk, scenarios,
attribution and factor profit and loss sections explain why they are unavailable.
Position-limit figures show without bands, passes or trim plans; a figure alone
above its limit proves a breach. Per-holding days to sell, valued-share multiples,
share sector and country weights, prices and the fund’s own performance stay
available. A future with a proven contra keeps its usual treatment. Unknown or
identified-security shorts that cannot be valued still require a usable total.
If a listing has no declared quote currency, the receipt says that the full
value cross-check could not run and why. When the comparable rows agree, the
fund keeps the provider’s stated weights, which do not come from Itoflow’s
quotes. The book note states when these refer to the provider’s total rather
than confirmed net assets; the receipt does not describe the whole book as checked.
Depositary receipts enter fund look-through as equity on their own listing.
When that listing has no reference type, other listings with the same checked
ISIN supply a type only when they agree. The engine keeps the original line.
A portfolio that holds one fund alone at weight 1 uses the fund’s own book.
When it also holds cash, or the fund’s weight differs from 1 beyond the 0.01
rounding band, the engine multiplies each fund holding by that weight and
keeps the cash. For example, 90% IFRA and 10% cash becomes 54% CAT, 36% NUE
and 10% cash if IFRA holds 60% CAT and 40% NUE. That book takes the date of
the fund’s holdings. For an earlier date, such as the start of a change in
risk, the engine applies today’s weights to the fund’s holdings on that date,
because today’s positions can’t show what the portfolio held then.
When a risk forecast check builds returns from holdings, a missing return
contributes zero and keeps its weight. The check measures return coverage on
the size of the risky holdings; cash adds no coverage. A session below the
required coverage is left out.
The forecast check reads the subject and comparator books on or before each
model date, known by the report day. These dates come from the model itself;
the check does not need the return-period calendar. Risk-only and
exposures-only runs also avoid that calendar.
News feed
GET /watchlists/{id}/news returns news and SEC filings stored in the last 24 hours that bear on the monitor’s holdings or its mandate. For a fund-oversight monitor, the holdings are the portfolio’s current positions, long or short, with funds expanded into what they hold. A fund whose newest holdings are more than 183 days old counts as itself, not expanded. Cash doesn’t count, nor does an import price placeholder, since it isn’t funded. Company weights add across direct positions and fund holdings; a company drops out when its total is known to be zero. Companies with unknown weights stay. For a research monitor, the holdings are its symbols.
Itoflow judges stored news for a monitor’s subjects when you ask: each company it holds, and its mandate where mandate matching is on. For a company, a model rates each item that could affect it from minor to material, with a direction. Company judgments are shared across monitors that hold the same symbol. Mandate judgments belong to one monitor: a model gives the chance that an item bears on what its mandate asks it to watch, and items at or above a fixed bar match. An item appears when it’s rated at least minor for one holding or matches the mandate.
Without
since, the feed returns the highest-scoring items. An item’s score for a holding is (m / 3) × (0.5 + 0.5 × w / w_max), where m is its materiality for that holding, w the holding’s weight, and w_max the largest holding’s weight (feed.largest_weight). A mandate match scores as a holding of weight 0 with materiality mandate_p × impact. The item’s score is its highest across its matches. For a research monitor, only materiality counts.
Fetch, then poll
feed.coverage says how many of the monitor’s subjects are judged through the last 24 hours. When current is below subjects, call POST /watchlists/{id}/news/fetch once. It returns 202 at once with the number of subjects and how many it sent to be judged; judging runs in the background, usually within a few minutes. A paused monitor fetches too, and calling again while judging runs is safe.
feed.judged_through as since, until feed.coverage.current equals feed.coverage.subjects. A poll reaches 5 minutes before since, to catch matches saved late, so it can return an item you already have: merge items by id. If a poll returns exactly limit items, some may not have fitted; read the feed again without since.
After you edit a monitor’s mandate, the feed leaves out the old mandate’s matches and counts the mandate as not current until a fetch judges the new text.
url and publisher:
Itoflow keeps items of impact 2 or more for 90 days, and others for 14 days. A company rating of notable or more keeps an item for 90 days.
A monitor that doesn’t exist, isn’t yours, is being deleted, or has a malformed ID returns
404 with error: "NOT_FOUND", from both routes. An invalid limit or since returns 400 with error: "INVALID_REQUEST".
Models
Setmodel_key to a fusion mode or a single model when you create or edit a monitor; edits without it keep the saved choice. New monitors without a choice use the plan’s default_mode from /pricing/model-access. Each report 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. Fusion modes do not use a connected ChatGPT subscription. See models and plans.
See the monitor endpoint reference for every field and error code.