Low-Level Design

Modules, APIs, data structures, algorithms and configuration.

Low-Level Design Document

Modules, Endpoints, Files, Data Structures and Algorithms

ICICI Direct • Interactive Brokers • Revolut

Embedded document image

Figure 1. Component relationships referenced by the detailed design.

1. Runtime components and files

Component / fileLocationDetailed responsibility
api_server.py~/breeze-appFlask host; Breeze routes; registers Revolut and IBKR blueprints.
revolut_processor.py~/breeze-appReads account/P&L CSVs; reconstructs holdings and summaries.
revolut_upload.py~/breeze-appValidates uploads, PIN, limits, backups and atomic snapshot publishing.
ibkr_agent_api.py~/breeze-appRefresh job state machine, claim/progress/upload/fail endpoints.
ibkr_windows_agent.pyWindows IBKR-TestPolls Oracle and executes the local exporter.
export_ibkr.pyWindows IBKR-TestConnects to TWS socket and writes ibkr_snapshot.json.
refresh_revolut_prices.py~/breeze-appRefreshes mapped Revolut prices and FX; preserves cache.
refresh_ibkr_prices.py~/breeze-appRefreshes prices/FX, applies fallback and enriches IBKR snapshot.
ibkr_agent_control.js/var/www/htmlOverrides dashboard refresh button and polls job status.
revolut_live.js/var/www/htmlCombines Revolut snapshot and cached price JSON client-side.
*.html/var/www/htmlStatic presentation pages.
.env~/breeze-appPrivate secrets and operational settings.

2. Flask endpoint specification

Method / routeAuthenticationRequestResponse / action
GET /api/healthSite authNoneBackend health JSON.
GET /api/funds, /holdings, /positionsSite auth + Breeze sessionQuery parameters as applicableBreeze portfolio JSON.
POST /api/update-sessionSite auth + admin PINsession_token, pinUpdates BREEZE_SESSION_TOKEN in .env.
POST /api/revolut/uploadSite auth + admin PINmultipart account_statement, optional pnl_statement, pinValidated snapshot rebuild and success metadata.
GET /api/revolut/statusSite authNoneSnapshot timestamp and holdings count.
POST /api/ibkr-refresh/requestSite auth + admin PINJSON pinQueues a new UUID job unless one is active.
GET /api/ibkr-refresh/statusSite authNoneCurrent job state.
POST /api/ibkr-agent/claimAgent tokenagentNameAtomically claims queued job.
POST /api/ibkr-agent/progressAgent tokenjobId, status, messageUpdates job state.
POST /api/ibkr-agent/uploadAgent tokenmultipart jobId + snapshotValidates/backups/publishes JSON.
POST /api/ibkr-agent/failAgent tokenjobId, messageMarks matching job as error.

3. IBKR refresh state machine

idle → queued → claimed → exporting → uploading → success ↘ error

StateEntered byMeaning
idleInitial/resetNo current job.
queuedDashboard requestWaiting for an online agent.
claimedAgentA named agent owns the job.
exportingAgentexport_ibkr.py is calling local TWS.
uploadingAgentSnapshot is being posted to Oracle.
successServerValidated snapshot published.
errorAgent/serverFailure reason retained for display.

4. Data structures

4.1 IBKR snapshot position

{ account, symbol, secType, currency, exchange, conId, quantity, avgCost, marketPrice, marketValue, unrealizedPnL, realizedPnL, priceSource?, priceRefreshedAt? }

4.2 Revolut holding

{ ticker, quantity, currency, estimatedCostBasis, estimatedAverageCost, lastActivityDate, activity:{buys,sells,dividends,splits}, currentPrice?, marketValue?, unrealizedPnL? }

4.3 External price cache

{ generatedAt, prices:{ SYMBOL:{price,currency,provider,providerSymbol,refreshedAt,...}}, fx:{"USD/GBP":{rate,provider,refreshedAt}}, errors:[], refreshSummary:{} }

5. Revolut processing algorithm

  1. Validate required account columns.
  2. Sort transactions by date.
  3. Maintain FIFO lots per ticker.
  4. BUY adds quantity and cost; SELL reduces earliest lots proportionally.
  5. STOCK SPLIT rescales quantities without changing remaining total cost.
  6. Negative MERGER - STOCK removes quantity; MERGER - CASH is excluded from active holdings.
  7. Ignore internal Revolut entity migration transfers to avoid double counting.
  8. Aggregate realised P/L and income from the optional P&L file.
  9. Write temporary JSON, reload for validation, back up prior snapshot, then publish.

6. Price refresh algorithms

6.1 Revolut

  1. Load mapping, snapshot and previous cache.
  2. Use Twelve Data for mapped USD positions and USD/GBP, EUR/GBP.
  3. Use Alpha Vantage for mapped GBP/EUR listings with GBX divisor where configured.
  4. Preserve old values for failed requests.
  5. Publish validated cache; dashboard calculates market value and P/L.

6.2 IBKR

  1. Load positions and ibkr_symbols.json.
  2. Use external quote where supported.
  3. If no external price exists, copy the snapshot marketPrice as an IBKR snapshot fallback.
  4. Refresh required currency/GBP pairs.
  5. Calculate marketValue = quantity × price.
  6. Calculate costBasis = quantity × avgCost.
  7. Calculate unrealizedPnL = marketValue − costBasis.
  8. Convert totals to GBP and write externalPricing metadata.
  9. Back up and rewrite the snapshot so the existing IBKR page consumes the enriched values.

7. Nginx routing

location /api/ { proxy_pass http://127.0.0.1:3000/api/; ... } location ^~ /api/ibkr-agent/ { auth_basic off; proxy_pass http://127.0.0.1:3000/api/ibkr-agent/; ... }

The narrow agent route bypasses website Basic Authentication to permit machine polling, but every Flask agent operation still requires X-IBKR-Agent-Token.

8. Configuration settings

SettingPurposeExposure
BREEZE_APP_KEY / SECRET / SESSION_TOKENICICI API authenticationPrivate .env
ADMIN_UPDATE_PINState-changing dashboard actionsPrivate .env; entered interactively
IBKR_AGENT_TOKENMachine authenticationPrivate .env + protected Windows config
TWELVE_DATA_API_KEYUS/FX/crypto quotesPrivate .env
ALPHA_VANTAGE_API_KEYMapped UK/EU quotesPrivate .env
Polling and delay valuesPacing and timeout behaviourPrivate config/.env

9. Logging and recovery

10. Error-handling requirements

ErrorHandling
Invalid admin PIN403; no state change.
Invalid agent token403; no claim/upload.
Wrong job ID409; prevent stale agent from publishing.
Invalid CSV/JSON400; retain old snapshot.
Provider limit/errorRecord error and retain cached/fallback value.
TWS timeoutAgent marks job error; retain old snapshot.
Permission/publish failureDo not replace working file; fix ownership and retry safely.

References