Repository navigation
v0.5.0 — JSON output, MCP server, and a pre-flight check that agrees with the solve
pip install --upgrade finport-optengine
A minor rather than a patch: this adds public API surface — an optional
dependency, a second console script, and a function lifted out of
run_engine — on top of a fix to a pre-flight check that was validating a
different mandate from the one it preceded.
Fixed
check validated a different mandate from the one optimize solved. On a
config with no expected_returns block it derived the vector as zeros while
run_engine derived it from the return history, so the pre-flight reported a
reachable return range of exactly zero to zero and would call a target
unreachable that the solve then reached. Both now go through
resolve_expected_returns, extracted from run_engine so the two cannot drift
apart again. Affects optengine check and the MCP check_mandate.
Added
An MCP server, optengine-mcp, behind the mcp extra (Python 3.10+):
pip install "finport-optengine[mcp]"
optengine-mcp # speaks stdio
Five tools — list_optimizers, describe_optimizer, check_mandate,
optimize, backtest — returning the same payloads as --json, from the same
module, so the two cannot disagree. Anticipated failures raise the SDK's
ToolError, which is the only class whose message reaches the client;
anything else is wrapped as "Error executing tool optimize" with the reason
discarded.
--json on optimize, backtest, check and describe. Human narration
moves to stderr, so stdout is one parseable document and an agent or pipeline
can act on a result without scraping a formatted table. Every payload carries
schema_version, and a command that fails before producing a result still
emits JSON — an object with error and exit_code — so a caller never has to
distinguish "no output" from "output I could not parse".
optimization_engine.reporting.payloads, the JSON contract as an importable
module rather than formatting buried in the CLI. Keys are chosen for the reader
instead of inherited from the attributes they came from, and a value absent
this run is null rather than a missing key, so a consumer can test a value
and never a key.
AGENTS.md and llms.txt — an API map for coding agents, including the
mistakes that cost real debugging time here: sample_dataset() returns prices
rather than returns, the solver is in result.extras, the backtest hashes are
on result.meta, and unconstrained max_sharpe puts 98.5% in cash on the
sample panel.
CI runs the MCP suite. The mcp extra is in no other job's install — it
cannot go in the 3.9-inclusive matrix — so those tests would have skipped
everywhere and looked like coverage.
Full detail in CHANGELOG.md.