Designing for High-Frequency Data in Shariah Signal
How we balance real-time market data updates with battery efficiency and UI performance in our Shariah screening tools.
Managing high-frequency data on a mobile device requires a constant negotiation between fresh information and hardware constraints. In Shariah Signal, our goal is to provide investors with immediate clarity on whether a stock aligns with ethical and Shariah-compliant standards. Because stock prices and market capitalization fluctuate by the second, the underlying financial ratios—such as debt-to-market cap—are also in constant motion. Delivering these updates without draining the user's battery or causing UI stutter requires a specialized approach to data flow and lifecycle management.
The Challenge of Perceived vs. Actual Real-Time
For a stock screening app, "real-time" is a spectrum. A day trader might require millisecond updates for execution, but for a Shariah screening tool, the requirements are different. The primary value is the compliance verdict. While the price influences the ratio, a change of $0.01 rarely flips a stock from compliant to non-compliant instantly. However, if the price on the screen is significantly delayed compared to the market, user trust erodes.
We faced a specific technical hurdle: how do we maintain a live connection to market data while ensuring the app remains a "good citizen" on the Android operating system? If we poll an API every second, we keep the radio active, preventing the device from entering low-power states. If we wait too long, the data feels stale. Our solution involves a tiered update strategy that adapts to what the user is currently doing.
Tiered Data Fetching Strategy
We categorize data updates into three tiers based on the user's focus and the volatility of the information. This prevents the app from fetching everything all the time.
- 1.Active Focus (The Watchlist/Detail View): When a user is looking at a specific stock, we use a WebSocket or high-frequency polling (every 5-10 seconds). This ensures the price and the resulting Shariah ratios are as accurate as possible during the decision-making process.
- 2.Passive Monitoring (Background): When the app is in the background, we halt all high-frequency updates. Instead, we rely on Reliable Android Background Tasks to perform periodic checks only if the user has set specific alerts for compliance changes.
- 3.Static Data (Financial Statements): Components like total debt or cash equivalents don't change by the second; they change quarterly. We cache these strictly and only refresh them when a new filing is detected, reducing the payload size of our real-time updates.
Managing State with Jetpack Compose
Updating the UI for high-frequency data can lead to "recomposition hell" in Android's Jetpack Compose if not handled carefully. If every tiny price fluctuation triggers a full screen redraw, the UI will feel sluggish. We use a combination of StateFlow and the distinctUntilChanged() operator to ensure that the UI only reacts when the change is meaningful.
For example, if the Shariah compliance status remains "Compliant" despite a price change, we may choose not to animate certain UI elements to save CPU cycles. We focus the "loud" UI updates on the compliance verdict itself, which is the core utility of the app. This philosophy of protecting the user's attention and device resources is something we also apply in Mindful Assistant, where we intentionally limit unnecessary notifications and visual noise.
Concrete Example: The Compliance Calculation Pipe
Consider the Debt-to-Market Cap ratio. The formula is: Ratio = (Total Debt / (Price * Outstanding Shares)) * 100
In a volatile market, the Price variable changes constantly. Here is how we process that in Shariah Signal to maintain efficiency:
| Step | Action | Data Frequency | Battery Impact |
|---|---|---|---|
| 1 | Fetch Total Debt | Quarterly | Negligible |
| 2 | Fetch Current Price | 5-10 Seconds | Moderate |
| 3 | Calculate Ratio | Local (On-Device) | Low |
| 4 | UI Update | Only if >0.1% change | Low |
By performing the calculation locally rather than requesting a pre-calculated ratio from a server every few seconds, we reduce data usage and latency. The server sends the raw price, and the app handles the Shariah-specific logic. This allows the app to remain responsive even on slower cellular connections.
The Role of Diffing and Debouncing
To prevent the UI from flickering, we implement "debouncing" on our data streams. If a stock price is bouncing rapidly between $100.01 and $100.02, we don't want the UI to reflect every single micro-tick. We wait for a short window (e.g., 500ms) of stability or a minimum threshold of change before pushing a new value to the view layer.
This is particularly important for the "Visualizing Financial Purity" aspect of our design. Sudden, rapid color changes from green to amber can be jarring for a user. We use smooth color transitions and data dampening to ensure the experience feels stable, even when the underlying market is not. We've discussed the importance of these visual states in our previous look at Visualizing Financial Purity: Designing Color for Shariah States.
Throttling for Battery Health
Android's Doze mode and App Standby Buckets are designed to prevent apps from wasting power. If Shariah Signal is kept open for long periods, we implement a "session timeout." After a period of inactivity—even if the screen is on—we reduce the polling frequency. A simple "Live updates paused - Tap to resume" overlay saves significant battery for users who might leave their phone on a desk with the app open.
We also leverage the ConnectivityManager to detect the type of network the user is on. If a user is on a metered connection or has "Data Saver" mode enabled, we automatically switch to a lower frequency update cycle. This respects the user's system-level preferences and ensures the app doesn't become a burden on their data plan.
Practical Implementation Checklist
When we build high-frequency data features, we follow this internal checklist to ensure quality:
- Is the data lifecycle-aware? Ensure all WebSockets or observers are disposed of in
onCleared()of the ViewModel oronStop()of the Activity. - Is there a visual indicator of staleness? If a data fetch fails, does the user know the price shown is 5 minutes old? We use a subtle timestamp or a "Syncing..." indicator.
- Can we batch the updates? If we are tracking a watchlist of 20 stocks, are we making 20 API calls or one call for 20 symbols? (We always aim for the latter).
- Is the calculation logic unit-tested? High-frequency data means more opportunities for edge cases. We test our ratio logic against extreme price swings to ensure the "Compliant" status doesn't glitch.
Engineering for Trust
In the world of Shariah-compliant investing, accuracy is a matter of conscience as much as finance. If our app says a stock is compliant, the user relies on that to make an ethical decision. By balancing real-time data with intelligent caching and battery-saving measures, we provide a tool that is both reliable and sustainable for daily use. We don't need to be the fastest ticker on Wall Street; we need to be the most reliable source of Shariah truth on the user's phone.
This engineering balance—speed vs. stability—is a core tenet at AIA Innovations. Whether it's calculating precise prayer times in Salah Companion or tracking market ratios in Shariah Signal, we prioritize the integrity of the data and the health of the user's device over flashy but wasteful features.
What to do next
- 1.Audit your observers: If you are building a data-driven app, check your ViewModels to ensure you aren't fetching data when the UI is not visible.
- 2.Implement Thresholds: Review your UI update logic. Can you skip a recomposition if the data change is below a certain percentage or threshold?
- 3.Test on Low Power: Run your app on an Android device with "Battery Saver" mode turned on. If it behaves poorly or drains the battery rapidly, consider implementing the tiered fetching strategy mentioned above.