ja/ar were missing the longbridge Data Sources table row and its place in
the US/HK fallback chains (a pre-0.1.12 drift; en/ko/zh already had them).
Now all 5 locales agree on the 23-source table + chains. (The en-only
'Using Longbridge explicitly' config subsection remains en-only.)
First slice of the Portfolio Studio roadmap item ("risk x-ray ... rest
Planned"): a pure-computation risk x-ray for weighted baskets, plus an
agent-facing tool that fetches closes through the standard loader
fallback chain.
backtest/risk_xray.py computes, over trailing returns only (no look-ahead
by construction): concentration (HHI / effective N / top-1 / top-3),
annualized and downside volatility, max drawdown with dates, historical
VaR + expected shortfall at 95/99, diversification ratio, and pairwise
correlation / beta vs an equal-weight proxy. Weights are validated and
renormalized with a warning; thin symbols fall out through a min-history
filter; every emitted float is finite-guarded so the payload always
survives json.dumps(allow_nan=False). Long-only for now — a short leg
changes concentration semantics and deserves its own slice.
The portfolio_risk_xray tool handles argument validation, shapes the
fetch envelope into a close panel (records with missing or mixed
timestamps fall back to loader order), and returns a strict-JSON
envelope with unresolved/skipped bookkeeping. Data fetching is
injectable for tests.
17 new tests cover the math on hand-built panels, the edge matrix
(renormalization, thin symbols, single asset, zero variance, bad
args), and the tool end to end with a stub fetcher. Full suite:
6037 passed, 12 skipped.
Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
MetaTrader5 SDK copy_rates_from_pos() returns numpy structured arrays
containing numpy.int64/float64 scalars. These types are not natively
JSON-serializable, causing TypeError when trading_history responses
are serialized downstream.
Add _int_or_none() and _float_or_none() helpers in reads.py and apply
them to all numeric fields in _rate_to_dict(). Add regression tests
covering numpy, plain-dict, and None input scenarios.
Closes#774
Signed-off-by: shadowinlife <shadowinlife@gmail.com>
Add the v0.1.12 cycle cohort (28 contributors) and demote the v0.1.11 list
into a collapsible block, in en/ja/ko/zh/ar. en/ja/ko keep English
descriptions; zh/ar translated.
Three fixes for the native zai provider on glm-5.1:
- get_llm_credentials now falls back to the provider catalog's
default_base_url when no *_BASE_URL is set, so CLI/manual-.env users
reach the canonical endpoint (Z.ai /api/coding/paas/v4) instead of
silently defaulting to api.openai.com. Web Settings already did this;
the backend credential path did not. Benefits all 22 providers.
- stream_chat falls back to a non-streaming invoke when a provider
streams zero chunks ('No generation chunks were returned'), instead of
raising ProviderStreamError. Scoped to the empty-stream case; genuine
provider errors still raise.
- ProviderStreamError appends a base-URL hint when the endpoint returns
an HTML error page (a common misconfiguration signal).
Fixes#758.
Two point-in-time correctness bugs in tushare_fundamentals.py:
1. `query_fundamentals` did not deduplicate after the PIT cut, so the same
(ts_code, end_date) could appear twice when both the original filing and a
later restatement were visible as of the query date. Fix: after the PIT
cut, keep only the row with the latest effective pit date per
(ts_code, end_date); ties preserve the last row in input order (natural
Tushare ordering where restatements follow originals).
2. `enrich_price_frames_with_fundamentals` fed the deduped snapshot directly
into merge_asof. This caused two problems: (a) the per-day PIT visibility
was evaluated on already-deduped data, making a restatement whose pit_date
was in the future appear as if it were always visible; (b) when a late
restatement for an *older* period (end_date < currently-visible end_date)
arrived, merge_asof picked it as the nearest-prior announcement, regressing
every subsequent snapshot to the older period.
Fix: enrich now calls the new internal `_query_pit_cut` (raw PIT cut, no
dedup) and builds an explicit forward-only effective timeline — a row is
only accepted into the timeline when its end_date >= the currently-visible
end_date. Same-period restatements (same end_date, later pit_date) pass
this check and appear as additional timeline entries; merge_asof then
surfaces the restatement value only from its own pit_date onward.
Fixes#771
Signed-off-by: klmtseng <20399135+klmtseng@users.noreply.github.com>
_BAR_MAP only listed lowercase 1h/4h, so runner-style 1H/4H fell
through to bar 1D and silently returned daily candles.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
_rest_timeframe only listed lowercase 1h/4h, so runner-style 1H/4H
fell through to 1Day and silently returned daily bars.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Unmapped intervals were lowercased, so project monthly token 1M became
yfinance 1m (one minute). Map 1M/1W explicitly like the yahoo loader.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Unknown intervals (including runner 4H) fell through to broker period 1d,
so hourly requests silently returned daily bars. Reject and return no data.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Blank holding_days become NaN under pandas and int(NaN) aborted the
validation CLI. Coerce non-numeric/blank values to 0 holding bars.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
When reported_value is 0 and fetched_value is not, verdict used float('inf')
and json.dumps emitted non-RFC Infinity tokens. Record null percents instead
and serialize with allow_nan=False.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Numeric CSV/Excel cells often stringify as 600519.0; the '.' made
_qualify_a_share treat them as already-qualified and skip .SH/.SZ.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Word/LLM paste often uses en/em/minus dashes in ranges like 1–10;
those were silently dropped because only ASCII '-' was recognized.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Shell-style export KEY=value lines were read as a literal key named export KEY, so Settings missed configured secrets and upserts appended a duplicate KEY= instead of updating the export line. Strip the export prefix on read/write like python-dotenv.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
One IC observation makes Series.std() (ddof=1) NaN, which leaked into ic_summary.json and the tool envelope. Treat single-sample std as 0.0 (same guard as metrics vol) and dump with allow_nan=False.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Explosive equity paths can set annual_return to +inf. The engine stdout
dump used default allow_nan=True and emitted bare Infinity tokens.
Sanitize non-finite scalars to null and dump with allow_nan=False,
matching options and run_card.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
A 100 → 0 → 50 equity path yields non-finite pct_change values that
poisoned Sharpe/Sortino/IR with NaN/inf. Skip those ratios (report 0)
when bar returns are non-finite, matching the options metrics path.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Halt-style NaN gaps can leave every polyfit window empty, so mean_slope
became NaN and leaked a bare NaN token into the tool JSON. Treat that as
0.0 and serialize with allow_nan=False, matching options_pricing.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
get_messages already skipped JSONDecodeError lines but still raised on
valid JSON that was not a Message mapping (null, extra keys). Skip those
too so later good lines remain readable.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
One unreadable or schema-invalid session.json raised during list_sessions
and aborted the whole listing; skip that entry and keep siblings.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
_to_yahoo_interval uppercased intervals before the map lookup, so project
interval 1m collided with monthly 1M and was sent to Yahoo as 1mo.
Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
Add P@5/MRR/NDCG@5 evaluation framework for memory retrieval A/B testing.
Benchmark compares Baseline (pure token overlap) vs Treatment (BM25 + importance
decay) on a 200-entry corpus with 50 annotated queries.
The benchmark suite is NOT intended for CI — it requires corpus files
(tmp/benchmark_corpus/) that are not version-controlled. The suite
automatically skips when corpus files are absent.
Corpus is derived from anonymized production agent sessions.
Usage:
python -m pytest agent/tests/memory/benchmarks/ -v
Refs: #732
Signed-off-by: shadowinlife <shadowinlife@gmail.com>
binanceusdm.fetch_leverage_tiers() routes to Binance's signed
GET /fapi/v1/leverageBracket USER_DATA endpoint and requires an API key,
even though the response carries no account-specific data. #716 called it
unconditionally for every -PERP fetch, so on merged main today any
perpetual fetch hard-crashes for callers without a Binance key.
- Remove the unconditional fetch_leverage_tiers() call (and the now-unused
_fetch_maintenance_brackets live-fetch method entirely). Execution/mark
OHLC and funding settlements go back to zero-credential, matching the
rest of the stack.
- Introduce a caller-supplied, versioned bracket artifact as the only way
to attach maintenance_brackets/maintenance_bracket_version: schema
version, symbol, provenance timestamp, per-tier fields plus an optional
notional_coefficient, and a content hash validated against the
canonical bracket JSON. Never fetched live.
- fetch(..., bracket_artifacts={code: artifact}) attaches brackets only
when a valid matching artifact is supplied for that code.
- fetch(..., require_brackets=True) makes a strict margin-risk consumer
fail closed with an actionable error before any network call when no
valid artifact is supplied for a -PERP code.
Per #462 / #716 follow-up discussion. No real bracket snapshot is
committed; test fixtures are synthetic. No Binance credentials are added
to the backtest path.
Signed-off-by: zygora <122336305+honginp@users.noreply.github.com>