Commit graph

28 commits

Author SHA1 Message Date
hermes
2c85acb829 feat(ownership): import IDX above-1% XLSX holder register
Since June 2026 IDX publishes the monthly "Pemegang Saham di Atas 1%"
list as an XLSX workbook on the Data Kepemilikan Saham page instead of
a PDF announcement. Add a parser for it and accept `.xlsx` in
`ownership import --file`.

- src/ownership/xlsx.rs: zip + quick-xml reader (shared strings incl.
  rich text, sheet cells), exact 12-column header match so the daily
  above-5% and investor-type/classification workbooks are rejected,
  Excel serial dates, numeric shares, percent -> bps with float-noise
  rounding. Builds KseiHoldingDraft directly and reuses the entity
  normalizers, so investor types stay uppercase like the PDF path.
- Fixtures: trimmed excerpts of the real 2026-08-31 above-1% and
  2026-09-23 above-5% workbooks.
- Unit + CLI tests: import, ticker, releases, above-5% rejection.
- Docs: ARCHITECTURE parser pipeline, AGENTS ownership inputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017a5Cv5Z1NzdYKgKnTiAF4E
2026-09-24 20:48:07 +00:00
hermes
09f7fe420c fix: satisfy clippy 1.97 lints failing on CI
- sanitize_current_ratio: and_then if/else -> filter
- screener/graph sorts: sort_by with reversed cmp -> sort_by_key(Reverse)
- insert_ksei_holdings_rows: manual Result match -> ?

Fixes the Clippy step on ubuntu-latest (rust 1.97) that the nix
toolchain (1.93.1) did not flag.
2026-07-31 12:14:58 +00:00
aad29eaf23 feat: default ownership sync to published snapshot 2026-04-12 14:27:47 +07:00
04eaa75882 fix: handle missing scrip column in April 2026 KSEI PDF
The April 2026 IDX ownership PDF omits the zero-valued scrip column for
some holders, causing the parser to leave holdings_scripless/scrip as
empty strings. This broke normalize_ksei_row which called parse_id_number
on empty input.

Two-layer fix:
- Parser: pop_numeric_tail handles 2-column (missing scrip) rows by
  defaulting scrip to "0"
- Normalizer: parse_id_number_or_zero backstop treats empty component
  share fields as 0 while still requiring total_shares

Also includes AGENTS.md refresh, formatting cleanup (rustfmt), and
version bump to 0.2.2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:15:19 +07:00
c94c826307 chore: prepare v0.2.1 release 2026-04-06 17:47:20 +07:00
1f5c4b2798 Add KSEI archive fallback import 2026-03-31 19:29:00 +07:00
8404b27628 Add ownership snapshot sync 2026-03-31 19:28:13 +07:00
a52712b063 Complete batch 2 ownership import hardening 2026-03-30 16:40:32 +07:00
a36648fd89 ownership: add IDX above1 discovery and import
Refactor KSEI PDF parsing for the live above-1 holder-register layout, add IDX announcement discovery plus browser-impersonated PDF fetches, and update the ownership docs to mark Batch 1 complete and scope Batch 2 around above1 hardening and unsupported legacy inputs.
2026-03-30 11:57:14 +07:00
76656de1f6 feat: cache, schema 2026-03-27 16:53:09 +07:00
7d32e9d69d fix(screen): debug the msn api, remove probelamtic msn api, filtering via client side 2026-03-18 11:09:51 +07:00
83d362afcd Fix clippy warnings for CI 2026-03-17 22:02:58 +07:00
65b95aa7b8 Fix config regressions and ownership import errors 2026-03-17 21:23:33 +07:00
Ciphercat
97502608c8 fix(cli): remove ignored financials and earnings flags 2026-03-12 17:07:24 +00:00
Ciphercat
cd4d8d8323 fix(api): reject empty ticker in resolve_symbol()
- Change resolve_symbol return type from String to Result<String, IdxError>
- Add early validation for empty/whitespace-only ticker input
- Return Err(IdxError::InvalidInput) for empty tickers
- Add InvalidInput variant to IdxError enum
- Update all 15 callers in cli/stocks.rs to handle Result with ? propagation
- Update tests: empty/whitespace tickers now return error

Fixes #7
2026-03-12 16:53:28 +00:00
Ciphercat
6671e22976 feat(ownership): complete ownership intelligence module
Sprints 0-8: Types, schema, KSEI parser, entity resolution, DB CRUD,
Bing API client, import pipeline, query commands, graph traversal,
changes diff, entity resolution CLI, FTS5 search.

- KSEI PDF parser (mutool stext + quick-xml, 99.2% accuracy)
- 7 query commands: ticker, entity, search, cross-holders, concentration, flow, releases
- Ownership graph with recursive CTE (ASCII tree + Graphviz DOT)
- Release diff/changes between KSEI snapshots
- Entity resolution CLI: unresolved, map, merge
- FTS5 trigram search on entity names
- Feature-gated under 'ownership' (default-on)
- 82 tests passing
2026-03-07 21:10:58 +00:00
Ciphercat
ed85428c90 feat: hybrid provider with Yahoo history fallback 2026-03-07 08:22:39 +00:00
Ciphercat
6d6d51a04f refactor(msn): remove HistoryProvider — Finance/Charts 404s on all IDX stocks
MSN Finance/Charts does not serve OHLCV data for XIDX stocks (returns 404).
Following the FP principle of not exposing capabilities a provider cannot fulfil:

- Remove impl HistoryProvider for MsnProvider entirely
- Remove fetch_charts from MsnClient
- Remove parse_chart_history, resample_history, trim_history_to_period from map.rs
- Remove MsnChart, ChartSeries, RawChart from raw_types.rs
- Remove parse_history_from_str, parse_close_only_history from parse.rs
- Decouple HistoryProvider from MarketDataProvider trait bound
- Add history_provider() factory: returns None for MSN, Some(Yahoo) for Yahoo
- CLI gates History/Technical on history_provider(), fails fast for MSN
- MSN mock returns Err(Unsupported); tests verify the behaviour explicitly
2026-03-06 20:55:35 +00:00
Ciphercat
a0da0a3adb feat(msn): implement full MSN Finance endpoint coverage
- Finance/Equities: company profile + executives (idx stock profile)
- Finance/Equities/financialstatements: balance sheet, cash flow, income (idx stock financials)
- Finance/Events/Earnings: EPS history + forecast (idx stock earnings)
- Finance/Charts: OHLCV chart history, unblocks MSN history command
- Finance/SentimentBrowser: crowd sentiment (idx stock sentiment)
- api.msn.com/insights: AI insights (idx stock insights)
- MSN/Feed/me: stock news feed (idx stock news)
- Finance/Screener: IDX universe screener with 8 presets (idx screen)
- Wire ProfileProvider, EarningsProvider, FinancialsProvider, SentimentProvider,
  InsightsProvider, NewsProvider traits on MsnProvider
- Remove HISTORY_UNSUPPORTED_REASON — MSN history now works via charts API
2026-03-06 19:32:56 +00:00
Ciphercat
3998e38ffc refactor: schema-driven architecture, capability traits, hardened error paths
- Split parse.rs into raw_types.rs (serde structs) + map.rs (pure transforms) for MSN and Yahoo
- Replace Yahoo fundamentals dynamic HashMap with typed structs (SummaryDetail, DefaultKeyStatistics, etc.)
- Introduce capability-based provider traits: QuoteProvider, FundamentalsProvider, HistoryProvider
- Add future MSN capability traits: ProfileProvider, EarningsProvider, FinancialsProvider,
  SentimentProvider, InsightsProvider, NewsProvider (all dead_code until wired to CLI)
- Add shared domain types in src/api/types.rs (CompanyProfile, EarningsReport, FinancialStatements,
  SentimentData, InsightData, NewsItem)
- Harden error propagation: Yahoo cookie auth, MSN partial fundamentals, history symbol context,
  cache clear failures
- Strict config parsing: invalid IDX_OUTPUT returns ConfigError instead of silent fallback
- Cache schema version enforcement: version mismatch treated as cache miss
- Extract fetch_with_cache() helper in cli/stocks.rs
- Add MSN retry/backoff parity with Yahoo client
- Standardize Option<T> policy through parse/map layers
- All 56 tests passing, clippy clean
2026-03-06 19:17:50 +00:00
0xrsydn
2cdefeb7a6 feat(api): add MSN Finance as alternative data provider
Add MsnProvider implementing MarketDataProvider trait with quote,
fundamentals, and history support. Includes provider-aware config
(file/env/CLI), cache namespace isolation per provider, symbol ID
mapping via embedded TSV, OHLCV resampling, and comprehensive unit
+ integration tests with MSN fixture data.

Key changes:
- MsnProvider with quote, key-ratios, and chart endpoints
- ProviderKind enum (yahoo/msn) with config hierarchy support
- Provider-namespaced cache buckets to prevent cross-provider poisoning
- Provider-aware MockProvider loading correct fixtures per provider
- Integration tests for config round-trip and cache isolation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:19:10 +00:00
Ciphercat
0d5b4b4755 feat(fundamental): add fundamental analysis suite (growth, valuation, risk, compare)
- Add Fundamentals type and MarketDataProvider::fundamentals() trait method
- Add Yahoo quoteSummary endpoint parser (/v10/finance/quoteSummary)
- Add analysis/fundamental.rs with exact signal thresholds ported from idx-mcp:
  - GrowthReport (revenue/earnings growth with signals)
  - ValuationReport (PE, PB, ROE, margin, EV/EBITDA with signals)
  - RiskReport (D/E, current ratio, ROA with signals)
  - FundamentalReport (composite with overall health signal)
- Wire CLI subcommands: stocks growth/valuation/risk/fundamental/compare
- Add table + JSON rendering for all report types
- Add mock fixture (quotesummary_bbca.json)
- 41 tests passing (22 unit + 19 integration)
- Known: Yahoo quoteSummary returns 401 from datacenter IPs (needs crumb auth)
2026-03-06 05:54:37 +00:00
Ciphercat
9182f25a01 feat(analysis): add technical analysis module and stocks technical command
- Add analysis module: SMA, EMA, RSI(14), MACD(12,26,9), volume ratio
- Add signal interpretation: bullish/bearish/neutral with consensus voting
- Wire up 'stocks technical <SYMBOL>' CLI subcommand
- Table output with colored signals + JSON output support
- Cache/offline/stale-cache fallback (same pattern as quote/history)
- Fetch 1 year of daily data for SMA200 coverage (~250 trading days)
- Add TechnicalReport, MacdSnapshot, VolumeSnapshot structs
- Add 4 new unit tests + 3 integration tests (30 total passing)
2026-03-05 22:46:32 +00:00
Ciphercat
eabd4f4ad7 cli: polish clap help text across commands 2026-03-05 19:34:47 +00:00
Ciphercat
dc1de5b344 style: cargo fmt 2026-03-05 18:33:20 +00:00
Ciphercat
c0a3d744b2 feat(cache): add file cache, cache commands, and offline fallback 2026-03-05 18:28:32 +00:00
Ciphercat
d2fa081266 feat(config): implement config init/get/set/path commands 2026-03-05 18:28:24 +00:00
Ciphercat
2174b42cff feat: implement idx-cli MVP foundation, provider abstraction, and core quote/history commands 2026-03-05 17:54:52 +00:00