Skip to content

feat: afterquote v1.0.0#5

Merged
Junaid2005 merged 13 commits into
mainfrom
v1.0.0
Jun 22, 2026
Merged

feat: afterquote v1.0.0#5
Junaid2005 merged 13 commits into
mainfrom
v1.0.0

Conversation

@Junaid2005

@Junaid2005 Junaid2005 commented Jun 21, 2026

Copy link
Copy Markdown
Owner

v1.0.0

Major feature release — point-in-time queries, cross-currency pricing, empirical validation, and uncertainty quantification.

Features

  • as_of parameterpricing() and info() accept point-in-time timestamps for historical queries. Fixes an import-time mutable default bug in __get_schedule.
  • FX adjustment — cross-currency pairs (e.g. 3TSL.L/TSLA) multiply in the FX return as a 1x leg alongside the leveraged underlying. GBp normalised to GBP.
  • CLIafterquote BASE UNDERLYING [--as-of] [--pricing]
  • Holdingsportfolio_pnl(path) reads CSV/JSON, returns per-position P&L + total
  • Cachelru_cache(128) on historical yfinance fetches (live paths bypass)
  • Benchmarkbenchmark(pair, days=90) daily backtest of synthetic vs actual next-day open. metrics() returns RMSE, MAE, direction hit-rate, tracking error.
  • Confidence bandinfo(confidence=0.95) attaches lower_bound/upper_bound from empirical residual percentiles. No Gaussian assumption.
  • Correlationpair.correlation(days=90) Pearson daily-return correlation, warns when |corr| < 0.5.

Other

  • Demo pair: 3TSL.L/TSLA (leverage + FX on one pair)
  • requires-python >=3.8 → >=3.10 (matches CI matrix)
  • Version 0.3.0 → 1.0.0

Test plan

  • pytest tests/ — 62 unit tests, no network, ~0.4s
  • pytest tests/ --runlive — 64 passed in 3.7s
  • afterquote 3TSL.L TSLA — CLI returns synthetic quote
  • afterquote 3TSL.L TSLA --as-of "2026-06-18 14:00:00-04:00" — historical query works
  • pair.correlation(days=90) on 3TSL.L/TSLA → 0.76 (high, no warning)
  • pair.info(confidence=0.95) → attaches lower_bound/upper_bound
  • benchmark(pair, days=90) + metrics() → RMSE 74.1, direction hit-rate 71%

Junaid2005 and others added 10 commits June 21, 2026 21:33
info() and pricing() now accept as_of: pd.Timestamp — resolves to now()
when omitted. Enables backtest-safe historical reconstruction without
look-ahead bias.

Also fixes __get_schedule mutable default (was frozen at import time)
and tightens is_exchange_open to schedule only the timestamp's own date.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
When base and underlying trade in different currencies, pricing() now
fetches the FX rate (e.g. USDGBP=X for 3TSL.L/TSLA) and applies it as
a 1x multiplicative leg alongside the leveraged underlying return.

Decomposes FX into gap/intra via _candle_returns() — same structure as
the underlying leg. Same-currency pairs (ccy_pair_yf=None) are unchanged.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
afterquote BASE UNDERLYING [--as-of TIMESTAMP] [--pricing]

Defaults to info() summary; --pricing prints full synthetic OHLC bars.
Wired up via [project.scripts] in pyproject.toml.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
portfolio_pnl(path, as_of=None) reads base/underlying/quantity columns,
builds a SecurityPair per row, and returns per-position P&L plus a
TOTAL row. pair_factory is injectable for testing.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
_fetch_history is a module-level lru_cache(maxsize=128) function keyed
by ticker + start + end + interval. get_history on YFinanceSecurity is
the injectable seam — fakes override it in tests. Explicit start/end
windows are deterministic so safe to cache unconditionally.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
benchmark(pair, days=30) walks each base trading session, applies the
leveraged+FX daily return to the prior close, and compares synth_open
to the actual next open. Returns base_close, synth_open, actual_open,
residual, direction_correct per session — NaN where the underlying had
no data (e.g. US holidays) so gaps are visible rather than silently dropped.

metrics(results) computes RMSE, MAE, direction_correct rate, tracking
error over valid rows only.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
info(confidence=0.95) attaches lower_bound/upper_bound from the
benchmark's empirical residual percentiles — no Gaussian assumption.
Benchmark routed through get_history to ride the existing lru_cache.
Fake security dispatches on interval so one pair runs both paths.
pair.correlation(days=90) returns Pearson daily-return correlation
between base and underlying. Emits UserWarning when |corr| < 0.5.
Standalone method — benchmark() and metrics() stay clean.
README adds confidence band, correlation, benchmark, holdings, CLI sections
and demo pairs table. CHANGELOG [1.0.0] covers all 8 features. AGENTS.md
bumps architecture from 3 to 7 modules.
@Junaid2005
Junaid2005 marked this pull request as ready for review June 22, 2026 20:34
@Junaid2005

Copy link
Copy Markdown
Owner Author

Made with opencode and glm 5.2! (and sonnet for the first half)

--confidence 0.95 attaches lower_bound/upper_bound to info output.
--benchmark runs daily backtest and prints results + metrics summary.
…ample outputs

Rewrites README to open with the concrete problem (LSE closes, TSLA
keeps trading), documents all CLI flags, and shows real truncated output
for every feature -- info(), pricing(), benchmark(), metrics(),
correlation(), portfolio_pnl(). Numbers consistent with live test run
(RMSE 74.1, direction hit-rate 71%, correlation 0.76). AGENTS.md CLI
line updated to reflect --correlation, --holdings, and mutual exclusion.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@Junaid2005
Junaid2005 merged commit 9a51470 into main Jun 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant