mirror of
https://github.com/we-promise/sure.git
synced 2026-06-07 11:49:02 +00:00
a3eb33b8a666df976b2bb167bef4ade7e281f7f3
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3e2990a52c |
feat(ibkr): compute net_market_flows from IBKR equity equity delta and trade flows (#1970)
* feat(ibkr): compute net_market_flows from IBKR equity delta and trade flows
Replace the hardcoded net_market_flows: 0 in HistoricalBalancesSync with an
exact derivation from IBKR's own equity summary data, eliminating any
dependency on third-party security price providers for Period Return.
Formula: nmf = Δnon_cash - net_buy_sell
- non_cash = IBKR equity total - materializer cash (exact per IBKR)
- net_buy_sell = sum of trade amounts converted to base currency using
the stored fx_rate_to_base (IBKR's own FX rate, already on Trade#exchange_rate)
Sets non_cash_adjustments = net_buy_sell so the virtual column identity
(end_non_cash_balance = start + nmf + adjustments) resolves to IBKR's
exact equity figure.
* test(ibkr): add sell-trade and no-trade nmf tests; fix memoization guard
- Add test: sell trades (negative amount) correctly isolate market loss in nmf
- Add test: no-trade scenario produces nmf = full Δnon_cash
- Fix: `return {} unless account` inside ||= exited the method without memoizing;
restructure to `if account ... else {} end` so the result is always cached
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ibkr): exclude dividend/interest trades from net_buy_sell; use historical FX date
Addresses two issues flagged in code review:
- P1: trades with qty=0 (Dividend, Interest) were included in net_buy_sell,
inflating/deflating nmf on dates with income events. Filter to qty != 0 at
the SQL level so only buy/sell trades affect the market-flow calculation.
- P2: Money#exchange_to defaulted to Date.current when no custom_rate was
stored, causing historical nmf to drift as FX rates change over time.
Pass date: entry.date so the fallback lookup uses the trade's own date.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(ibkr): cover Money::ConversionError fallback in trade_flows_by_date
Adds a test that stubs Money#exchange_to to raise ConversionError for a
cross-currency trade with no stored exchange_rate, verifying that the
rescue clause falls back to entry.amount and that nmf and
end_non_cash_balance still resolve correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ibkr): log warning when FX conversion falls back to unconverted amount
When Money::ConversionError is raised for a cross-currency trade with no
stored exchange_rate, warn with entry currency, account currency, date,
amount, and entry/account IDs so the silent fallback is visible in logs.
Same-currency ConversionErrors (unexpected but possible) stay silent.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ibkr): skip unconvertible FX trades, redact log, tighten join
- On Money::ConversionError, skip the entry from net_buy_sell rather
than falling back to the raw amount (which treated e.g. EUR as CHF);
nmf now absorbs the full Δnon_cash for that date instead of silently
misstating period return
- Remove entry amount, entry ID, and account ID from the FX warning log
to avoid exposing financial data in log output
- Consolidate entryable_type guard into the JOIN condition rather than a
separate WHERE clause
- Add inline comment on the first-day zero case to distinguish intent
from a bug
- Update ConversionError test to assert skip behavior (nmf=200, not 50)
* fix(ibkr): exclude dates with unconvertible FX trades from balance upsert
* fix(ibkr): skip upsert_all when all balance rows are filtered by failed FX dates
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|
|
6262b0a493 |
fix(ibkr): correct historical cash/non-cash split for linked accounts (#1813)
* fix(ibkr): resolve weekend balance oscillations and improve data processing Address issues where IBKR weekend/holiday data caused incorrect balance calculations and improve the robustness of IBKR account processing. - Fix historical balance oscillations by ignoring anomalous weekend rows and filling gaps by carrying forward the last known trading day value. - Normalize report dates to the last trading day to ensure consistency. - Improve `HoldingsProcessor` to skip individual bad lots instead of failing the entire group. - Refactor `ActivitiesProcessor` to accumulate fee counts locally via return values instead of using instance variables. - Add support for accounting parentheses notation in `DataHelpers`. - Memoize the account object in `IbkrAccount::Processor` to reduce database queries. - Update tests to reflect date normalization and improved precision assertions. * fix(ibkr): derive historical cash from materializer balances, not equity summary Real IBKR Flex exports do not include a reliable cash/stock breakdown in EquitySummaryByReportDateInBase — only the total is consistently present. The previous implementation parsed the missing cash field as zero and wrote cash_balance=0 for every historical date, causing negative and wildly incorrect cash values throughout the account history. Instead, read the materializer's already-computed cash_balance for each date (derived from holdings via the reverse calculator) and use only IBKR's total as an authoritative balance anchor. This is consistent with how present-day balances are handled and requires no weekend/holiday filtering since IBKR does not emit weekend rows and holiday totals are legitimate data points. Also accept equity summary rows without an explicit currency field (some Flex configurations omit it) and explicitly reject BASE_SUMMARY aggregate rows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: simplify boolean coercion in import_commission_transaction Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ibkr): cover trailing weekend gap and align qty with valid lots HistoricalBalancesSync: extend fill_gaps to account.current_anchor_date so days after the last equity summary row (e.g. Saturday/Sunday when a sync runs over the weekend) are also overridden rather than left with the materializer's stale total=cash value. HoldingsProcessor: replace separate quantity sum + weighted_cost_basis_for with a single valid_lots method that computes both from the same set of parseable lots. Previously a lot with a valid position but unparseable cost_basis_price was excluded from the cost basis calculation but still counted in quantity, producing inconsistent qty/cost_basis values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * review: address PR feedback on ibkr fix branch - Remove all "Fix N:" review-artifact comment labels - Add Sentry.capture_message for silenced anchor repair failure so it surfaces in production monitoring - Add Rails.logger.warn for zero/nil total rows skipped in HistoricalBalancesSync - Document normalize_to_last_trading_day holiday limitation and why gap-fill covers it - Rewrite two non-obvious comments to stand alone without the label prefix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: remove alignment padding in balance_rows hash Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ibkr): address two P1 review findings - Allow zero and negative equity summary totals through HistoricalBalancesSync so fully-liquidated and margin accounts are not silently skipped (which would cause fill_gaps to propagate a stale non-zero total forward). - Remove normalize_to_last_trading_day from HoldingsProcessor: shifting weekend report_dates to Friday caused Balance::SyncCache#get_holdings_value to find no holdings on Saturday/Sunday (exact-date lookup), collapsing non_cash to zero — reintroducing the very oscillation the fix was meant to prevent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(ibkr): add tests for historical balances sync and data helpers - Add test case to verify non-cash balance calculation in historical balances sync - Add test case to ensure rows with unparseable or nil totals are skipped - Add new test file for IBKR data helpers * fix(ibkr): prevent date range overflow during historical sync Adjust the calculation of `last_date` in `HistoricalBalancesSync` to ensure it does not exceed the current anchor date or today's date. This prevents the sync process from attempting to fetch or process future dates, which was causing oscillations in weekend data. Also remove the conditional check for Sentry before capturing error messages in the account processor. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
ce5d7dd736 |
Add Interactive Brokers Provider (#1722)
* Display multi-currency holdings correctly * Implement IBKR provider * Fix: Use historical exchange rate for historical prices * Add brokerage exchange rate for trades * Sync historical balances from IBKR * Add logos in activity history * Fix privacy mode blur in account view * Improve IBKR XML Flex report parser errors |