Stock API Price Alerts Need State as Well as a Price Threshold
Summary: A stock API can supply prices for an alert, but a successful subscription does not define when a notification should fire. A useful alert needs an observation type, a trigger rule, remembered state, and a policy for missing data. In a synthetic five-update example, checking whether the price exceeds $100 produces three matches, while detecting an observed upward crossing produces two events. The distinction prevents repeated updates above the threshold from becoming repeated crossing alerts.
What the API contributes to a price alert
A stock API gives software access to stock-related observations, such as recent prices, trades, quotes, or historical bars. A price alert is one application of that data. The API supplies observations; the application decides which observations qualify, whether the rule has changed state, and what message to deliver.
That division matters even for a small watchlist. The expression price > 100 answers whether the current value is above a threshold. It does not say whether this is the first time the application has seen that condition, whether a notification has already been sent, or what happened during a disconnection.
For a straightforward implementation, start with one instrument and one definition: notify when two consecutive eligible observations move from at or below $100 to above $100. βEligibleβ means that the observations meet your chosen price type, feed, session, freshness, and ordering requirements. This is an observed crossing in the data your application accepts; it is not a claim that every market event was captured.
TickDB's ticker documentation, for example, provides stock messages with a symbol, a latest-price field, and a timestamp. Those are useful inputs to an alerting application. Reading that schema does not establish that a ticker update represents every individual trade, nor does it supply the application's notification policy.
Figure 1. Suggested application flow. Eligibility, trigger state, and notification delivery are separate responsibilities; the diagram is not a provider architecture or a delivery guarantee.
Decide whether the user wants a condition or a crossing
Suppose five accepted observations arrive in this order: $99, $101, $102, $100, and $101. These are synthetic values, not a market replay.
Checking price > 100 matches the second, third, and fifth observations. That can be appropriate for a status indicator that stays active while the condition is true. If each match sends a message, however, a user asking for an upward-crossing alert receives an extra notification at $102 even though the previous observation was already above $100.
A crossing rule compares the current observation with the previous eligible one. It fires at the second and fifth updates. The fourth update, exactly $100, puts the rule back on the at-or-below side. Under this definition, reaching $100 is not an upward crossing; moving above it is.
There are other valid policies. A one-time target alert can deactivate permanently after its first event. A condition alert can notify immediately when enabled above the threshold. A crossing alert can use the first observation only to establish a baseline. Choose one behavior and describe it in the interface. Quietly mixing them makes it difficult to explain apparently missing or repeated messages.
Figure 2. Synthetic observations for a threshold of $100. Values above the threshold occur three times; upward crossings between accepted observations occur twice.
Choose data that can answer the rule
An alert about the latest reported trade, the best ask, and a bar close represents three different tasks. A daily-close alert can use completed daily bars under an explicit session policy. An intraday trade alert needs observations appropriate to that definition. A latest-price field with unclear semantics is not enough to claim either behavior.
Polling also limits what the application can observe. Imagine two polls both return $99, while the price briefly rises to $101 and returns between them. Comparing the two snapshots cannot reveal that excursion. A bar high may indicate that the interval contained an above-threshold value, but it does not reconstruct every crossing or its exact sequence.
Streaming can reduce that sampling gap, but its usefulness still depends on the feed and channel. A ticker stream may summarize changes; a trade stream has its own coverage and filtering rules. Neither a WebSocket connection nor the word βreal-timeβ proves complete observation of every relevant event.
Subscription success is another separate check. Alpaca's streaming documentation distinguishes connection, authentication, and subscription, and returns the active subscription list after changes. An application should verify the requested feed and symbols rather than treating an open socket as proof that the intended observations are arriving.
A minimal observed-crossing detector
The following Python example isolates the rule from the network and notification service. It requires only the standard library. Prices are synthetic decimal strings, and the caller must provide already validated, ordered observations for one rule. The threshold is fixed at $100 for this example.
from decimal import Decimal, InvalidOperation
class UpwardCrossing:
def __init__(self):
self.threshold = Decimal("100")
self.previous = None
def reset(self):
self.previous = None
def observe(self, text):
try:
price = Decimal(str(text))
except InvalidOperation as exc:
raise ValueError("Expected a decimal price") from exc
if not price.is_finite() or price <= 0:
raise ValueError("Expected a finite positive price")
crossed = (
self.previous is not None
and self.previous <= self.threshold < price
)
self.previous = price
return crossed
# Synthetic observations; no API call or message delivery.
rule = UpwardCrossing()
prices = ["99", "101", "102", "100", "101"]
events = [i for i, p in enumerate(prices, 1) if rule.observe(p)]
print(events) # [2, 5]
Repeated observations on the same side of the threshold do not produce another crossing. An initial value above $100 produces no event because the rule has no earlier baseline. Invalid numeric input raises an error without replacing the previous value. The surrounding application must decide whether that error also means continuity is uncertain and requires a reset.
Use separate state for each instrument and rule configuration. Do not feed several symbols through one instance or change the price definition while retaining the old baseline. This small detector does not validate timestamps, identify duplicate events, process corrections, persist state, or send notifications.
It also does not suppress repeated genuine oscillations around $100. A cooldown limits notification frequency, while hysteresis requires a lower rearming level before another trigger. Both change the user-visible policy. Add them only when their behavior matches the alert the user requested.
A reconnect cannot fill in an unseen interval
Suppose the last accepted value before a connection loss was $99 and the first value after recovery is $101. The endpoint observations are on different sides, but the application did not observe the intervening sequence. Its UI should not imply that it watched a specific crossing happen continuously.
One conservative policy is to mark the rule unavailable during the interruption, reconnect and restore the subscription, then use the first eligible observation as a new baseline. In the example, the caller invokes reset() when continuity is lost. The next call to observe() establishes state without firing. This deliberately sacrifices possible alerts during the gap in exchange for a clear live-observation policy.
TickDB's WebSocket guidance explicitly calls for resubscribing after reconnect and notes that full-market subscriptions receive another initial snapshot. That describes how to resume receiving data. A snapshot establishes current state; it does not reconstruct the sequence of missed observations. Where suitable history is available, a separate recovery process can evaluate it and label resulting notifications as retrospective.
The same policy question arises at startup, a session change, or a restart that loses in-memory state. Persisting the previous price alone is insufficient if you cannot establish continuity with the next observation. Record the interruption and the rule's status so that silence is not mistaken for evidence that the threshold was never crossed.
Detecting an event and delivering it are separate outcomes
An alert event can be detected correctly while the notification service is unavailable. Conversely, retrying a delivery after an uncertain response can produce duplicate messages even if the crossing detector ran only once.
For a durable implementation, persist the updated rule state and its alert event together, then let a delivery worker process that event with a stable identifier. Track pending, delivered, and failed attempts separately. Where the destination supports idempotency, reuse the event identifier on retries. If it does not, an ambiguous delivery result can still leave a duplicate risk; the price rule cannot solve that on its own.
This is an application design recommendation, not a guarantee supplied by a stock API or by the sample code. A market-data subscription also does not place a trade. Order submission and execution belong to a separate workflow with its own account permissions and outcomes.
Verify the behavior the user will actually see
Before connecting live data, run a short synthetic sequence through the rule and inspect the events. Include an initial value above the threshold, several values staying above it, a return to exactly the threshold, a new upward crossing, and a reset during a gap. Then exercise the surrounding application with stale inputs, out-of-order observations, a failed subscription, and notification retries.
An open source client can help receive and parse data, but it does not choose these policies for the application. The useful promise is precise: which observations qualify, what transition creates an event, when the rule is unavailable, and how delivery status is reported. That gives a stock API alert a meaning the user can understand and a behavior the developer can verify.
Sources consulted on November 3, 2026: TickDB Docs, Real-Time Quotes and WebSocket Best Practices; Alpaca, WebSocket Stream. The code and price sequences are offline demonstrations. No live feed completeness, latency, notification delivery, or trading performance is claimed.



Top comments (1)
Your account is in the pending status.