Web · Data pipeline · Warsaw & US markets

How we built TickerFlow: an alert system that watches the market for the investor

TickerFlow came out of a frustration we had ourselves: a stock alert system for the Warsaw Stock Exchange and the US markets. An investor defines once what they are waiting for - which companies, and at what price or volume condition - and the system watches the market for them, then says so at the exact moment the condition is met. The whole of it is ours, from first commit to production. This case study is how we approached that work, and where the real difficulty lay - not in the idea, but in the data, its cost and its quality. Client work gets the same treatment of what sits underneath.

Platform
Web
Markets
GPW, NASDAQ, NYSE
Data
Post-close pipeline
Signal
Email notifications
TickerFlow stock alerts dashboard
TickerFlow: a condition defined once, a notification exactly when the market meets it.
Problem
An investor cannot watch thousands of instruments all day to catch the single moment the market confirms their thesis.
What we built
An end-of-day alert system for the Warsaw and US exchanges - define a price or volume condition once, get told exactly when the market meets it.
Outcome
A post-close pipeline over nearly 7,000 instruments across NASDAQ, NYSE and GPW and more than a million historical records, with a data-quality layer and on-time email alerts.

What this case study covers

  1. The product we set out to build
  2. A signal, not constant watching
  3. How we approached the build
  4. Market data: why multiple sources
  5. Cost optimization: every query costs money
  6. A high bar for data quality
  7. The daily pipeline after the close
  8. Scale: thousands of instruments, millions of records
  9. Thresholds defined by the investor
  10. Alerts worth taking seriously
  11. Notifications that arrive on time
  12. The web app
  13. The knowledge base
  14. Reliability: a run that cannot fail silently
  15. What this build shows about how we work
  16. What we would tell another team
  17. Frequently asked questions

The product we set out to build

Watching the market takes time, and that is the problem TickerFlow starts from. An investor has often already done the hard part: they have chosen the companies they consider good and want to buy. They do not want to buy them at just any moment, but at a specific one, when the market confirms their thesis - for example when volume on a stock rises clearly, or the price breaks an important level. The trouble is that there can be dozens of such companies on a watchlist, thousands of instruments on the market, and nobody can sit all day watching every one of them at once.

In practice this means a tedious daily ritual: scanning quotes, checking whether anything that was being waited for has happened on any of the watched companies, and a constant unease about having missed exactly the moment the whole list was built for. It is work that eats attention, and most days end with the conclusion that nothing happened - which still had to be checked to be sure.

What we built inverts that burden. Instead of making a person watch the market, the system watches the market for them. The investor defines once what they are waiting for - which companies, and at what price or volume condition - and can then get on with their life. When the condition genuinely occurs, a notification arrives. What it took to make that simple promise hold, and where the real difficulty turned out to sit, is the rest of this page.

Instead of making a person watch the market, the system watches the market for them.

The cost of that constant watching is twofold. The first is time - real hours a week spent scanning quotes that mostly come to nothing. The second, less visible, is the cost of missing: a single well-caught moment can matter more than weeks of observation, and missing it stings long after it has happened. A product that takes the watching off a person's shoulders gives back both - the reclaimed time, and the confidence that they have not missed what they were waiting for.

It is worth stressing that this is not a tool for making decisions on the investor's behalf. It does not say what to buy or when to sell - those decisions stay with the person, because it is their money and their strategy. The product's role is narrower and more honest: to make sure the moment they are waiting for does not slip past them simply because they happened to be looking the other way.

A signal, not constant watching

At the heart of TickerFlow lies an assumption older than any technology: a good decision is not the one made most often, but the one made at the right moment. Jesse Livermore, one of the most famous speculators in history, used to say that a stock is worth buying only once volume confirms it - once there is real interest behind a price move, rather than a random flicker. The idea is simple: the point is not to watch the market endlessly, but to react when a specific signal appears.

This distinction shapes the whole product. TickerFlow does not try to be yet another screen full of charts to stare at. It is the opposite of such a screen: it stays silent while nothing important is happening, and speaks up exactly when a condition the investor defined is met. The value is not the amount of data shown, but the relevance of a single notification at the moment it genuinely matters.

For the person using it, the change is fundamental. Instead of actively hunting for a signal in the noise of thousands of instruments, they describe the signal once and delegate the hunting to the system. That moves the work from the human to the software, exactly where software is better - because it does not tire, does not forget, and watches every company at once.

There is also a truth about human nature in this, not only about the market. A screen full of data, however good, demands that someone look at it - and the longer nothing happens, the less often it gets a glance, until it stops being watched on the very day something happens. A notification works the other way round: it asks for no attention until it is needed, and when it is, it asks for it itself. For a product whose entire value is catching the right moment, that is the difference between a tool that genuinely helps and one that looks good and gets ignored.

How we approached the build

The risk on TickerFlow was never in the interface - it was in the data. A screen for setting thresholds and a notification landing in an inbox were the easiest part of the job. A product that sends alerts based on data that is incomplete, late or wrong is worse than no product, because it undermines trust exactly where money is involved.

So we started with the hardest questions: where to get reliable data on thousands of instruments, how to do it without costs that eat the point of the product, and how to detect that data from a source is simply bad before it turns into a false alert. These were the questions that decided whether the product had any reason to exist, so we settled them first, and built the interface and the notifications around a working, trusted core of data.

The sections below run in build order: data, cost and quality first, then the logic of thresholds and alerts, then the part a user actually sees. Where a product succeeds or fails on what sits underneath it, that is the only sensible order to work in.

Market data: why multiple sources

All of TickerFlow stands on market data, and that turned out to be the hardest part of the puzzle. There is no single perfect source that would hand over a complete set of reliable, current data on every instrument from the Warsaw exchange and the US markets on sensible terms. Every source has its strengths, its gaps, and its own way of occasionally being wrong.

So we built the product to integrate different data sources rather than tie itself to one. Combining them gives a fuller and more resilient picture: what is missing in one place is often present in another, and a discrepancy between sources is itself a signal that something is off with one of the datasets. It does, however, require reconciling information that arrives in different formats, with different conventions and at different times - and doing that consistently, for thousands of instruments, every day, is far harder than it looks from the outside.

Reconciling sources is not only a matter of formats. The same instrument is sometimes labeled differently in different places, quotes from the Warsaw exchange and the US exchanges close at different hours and in different time zones, and what one source reports as a closing price another may compute slightly differently. Building a single, consistent picture of each company from all of this takes a set of rules that reconcile those differences repeatably, not case by case.

A separate problem is corporate actions: splits, dividends, reverse splits. To a person it is obvious that after a share split the price drops in proportion to the split ratio with no real move at all; to a system computing thresholds it is a potential false alarm on an enormous scale. History has to be adjusted consistently for such events, or yesterday's split turns into hundreds of meaningless notifications today. It is one of those details that stays invisible until it is done wrong.

It is fair to ask why not simply rely on one good, paid provider. The answer is practical: even the best single source has days when something is missing or something is reported wrong, and tying the whole product to it means its bad day becomes a bad day for every user. Multiple sources are not an extravagance but insurance - and at the same time a way for them to check one another.

Integrating multiple sources is a decision that costs more work up front, but it is the foundation of trust in the product. The alert TickerFlow sends is only as good as the data it rests on, and that data has to be complete and checked before anyone makes a decision about money on the strength of it.

Cost optimization: every query costs money

There is a catch here that can overturn the economics of the whole product: access to market data costs money, and data aggregators charge for queries. For one company it is negligible. For thousands of instruments, checked regularly, the naive approach - just ask for everything whenever needed - generates a bill that grows faster than any value the product could deliver.

Cost optimization was therefore not an add-on but a condition of existence. We had to design what the system asks for, when and how often - so that it fetches what is genuinely needed, does not pay twice for the same thing, and does not poll sources more often than the data warrants, given that the data itself updates on a fixed rhythm. It is a constant game between completeness and cost: the data has to be fresh enough for an alert to have value, yet fetched frugally enough for the product to add up.

In practice this means a good deal of work on not fetching twice what is already held, and not asking for data that could not have changed anyway. History, once fetched, does not age, so there is no reason to reach for it again; what matters is mostly what the latest session added. It sounds trivial, and at the scale of thousands of instruments and multiple sources it decides whether the monthly data bill is a fraction of what the product can earn, or a multiple of it.

Optimizing for cost also changes what is feasible at all. When every query is cheap or free, everything can be checked, all the time, without a second thought. When every query costs, the design of the product and the design of its economics become the same task: how often and about what the system asks follows both from what the user needs and from what the product can afford. Reconciling the two is part of the engineering, not a separate line in a spreadsheet.

The same discipline has one more benefit: scalability. A product that queries frugally from the start grows more cheaply - adding more companies or more users does not multiply the bill at the same rate as the naive approach. Cost, instead of being a brake on growth, stops being a problem that has to be thought about constantly.

A high bar for data quality

Since the alerts concern money, the bar for data quality has to be high - and that was one of the tougher requirements of the whole project. Data from external sources can be wrong in many ways: a missing trading day, a value that is obviously unreal, a price adjusted in one source but not another, zero volume where the data was simply absent rather than there being no trade. Each of these cases, taken uncritically, turns into a false alert, or into silence where an alert should have fired.

So we built in a layer that treats source data as untrustworthy by default. Values are checked for plausibility, compared across sources where possible, and flagged when something deviates enough that a data error is more likely than a real market event. It is better to withhold an alert resting on a suspect value than to send a notification that turns out to be the result of a typo in the data.

It is worth naming the kinds of error, because each needs a different response. An extreme value - a price ten times too high, a volume with an extra zero - is easy to catch with a plausibility rule. Harder are the subtle ones: a price that differs by a few percent between sources, or a day that is missing from one dataset but present in another. The most dangerous are the ones that look perfectly normal and are simply untrue - and there the only defense is comparison across sources and the historical context that suggests what is plausible for a given company.

There is also a quieter version of the problem: not a wrong value, but its absence. A source that fails to deliver quotes for some companies on a given evening does not report an error - it simply stays silent. Without deliberately handling such a gap, the product would decide that nothing happened on those companies and would not send the alerts it should. That is why we treat completeness as seriously as correctness: missing data has to be detected and told apart from a real absence of movement.

Quality itself also has to be measurable, not merely declared. We compare data across sources, set it against history, and watch how often the control layer catches something - because a sudden rise in the number of flagged anomalies is itself a signal that a source has started delivering junk. Without such a measure, "we care about data quality" is only a declaration, and for a product about money a declaration is not enough.

This distinction - between a real event and an artifact of bad data - is the core of whether the product can be trusted. An alert is a promise that exactly the thing the investor was waiting for has happened. If that promise turns out even once to be the result of junk in the data, the user stops taking notifications seriously - and then the whole product loses its point, however nicely it looks.

The daily pipeline after the close

TickerFlow runs to the rhythm of the exchange. After the session closes, a daily process starts that fetches the day's data, processes it and checks it against the conditions set by every user. It is a deliberate model choice: the product rests on session data - on what happened over the trading day - rather than on tracking every price flicker in real time, which would be both far more expensive and far more prone to noise.

Such a batch run sounds simple and hides a good deal of engineering. It has to process data for thousands of instruments in a reasonable window of time after the close, so that notifications arrive before they go stale. It has to cope with some sources being slow or incomplete on a given evening. And it has to do the same thing, reliably, every trading day, because a missed run means missed signals - and a user who once fails to get an alert they know should have fired rightly loses trust.

The time pressure here is real. The window after the close in which a notification still has value is not unlimited - an alert about yesterday's signal that arrives in the middle of the next session is already late. That means the whole run, from fetching data across every source to sending the last email, has to fit inside a tight time budget, even on evenings when one of the sources is slow. That is why the order and parallelism of the work are not accidental: whatever can be computed early is computed early, so that the smallest possible part is left depending on the slowest source.

The run also has to be safe to repeat. If something fails halfway and it has to be started again, it must not send the same alerts twice or count part of the data twice. Designing it so that it can be safely resumed, and the result is always the same however many times it ran, is one of the things that separate a process that can be trusted from a script that usually works.

Scale: thousands of instruments, millions of records

Scale makes this a challenge in its own right. TickerFlow covers close to seven thousand instruments across NASDAQ, NYSE and GPW, along with over a million historical records - and it is against history that many conditions make any sense at all. "A clear rise in volume" means nothing without a point of reference: one has to know what volume is normal for a given company in order to judge that today's is unusual.

Maintaining and processing that history, without blowing up either cost or run time, is another layer of the same data puzzle. History has to be complete and consistent, because a threshold computed on holey data gives either false alarms or silence at the wrong moment. And the longer and richer the history, the better the reference points - and the more work to compute all of it quickly and cheaply every evening.

The point of reference has to be computed separately for each company, because "normal volume" for a liquid NASDAQ giant and a thin stock on the Warsaw exchange are two completely different worlds. The same condition - "a clear rise" - has to mean something different in each case, and that meaning comes precisely from the history of that instrument. Keeping those individual reference points current, for thousands of companies, is part of the work that makes one simple condition behave sensibly across the whole spectrum of the market.

Thresholds defined by the investor

The heart of the product from the user's side is thresholds. The investor describes what they are waiting for: which companies interest them, and what condition should trigger them - crossing a price level, an unusual rise in volume, a combination of the two. They are the one who knows what their thesis is and what signal confirms it; the product's job is to faithfully watch for exactly what they asked.

Simplicity on the outside hides design decisions underneath. Conditions have to be flexible enough to express real strategies, yet understandable enough that someone who is not a programmer can set them without a manual. It also has to be defined unambiguously when a condition counts as met - because "a rise in volume" sounds obvious until it has to be turned into a precise rule that works the same for a liquid NYSE stock and a thin instrument on the Warsaw exchange.

Before a condition goes live, it helps to know how it would have behaved in the past. Being able to check a threshold against historical data - how many times it would have fired, on which companies, at which moments - turns setting an alert from guesswork into a deliberate decision. It is also the best defense against an over-sensitive condition: if it would have fired every day in the past, it will probably fire too often now for anyone to listen to it.

A well-designed threshold is one where the user gets exactly the alerts they asked for - no more and no less. Conditions that are too sensitive flood them with noise and teach them to ignore notifications; conditions that are too rigid let through exactly the moves the product exists for. Hitting that balance is as much interface design as it is understanding how people actually trade. In practice strategies vary: one investor waits for a break above a yearly high on elevated volume, another for quiet accumulation below a certain level, another for an unusual move in turnover regardless of price. The product has to express those different intentions without forcing anyone to think like a programmer.

Alerts worth taking seriously

All of TickerFlow's value converges on one moment: when the notification arrives. Everything else - data, cost, quality, the pipeline - exists so that this one moment is credible. An alert that comes too late is useless; an alert that comes without backing in reality is worse than useless, because it does harm. Punctuality and truth are therefore where most of the effort went.

Punctuality comes from the rhythm of the run: the post-close process is arranged so that the signal reaches the investor while it still matters for a decision on the next session. Truth comes from the data-quality layer: an alert fires only when the condition was met on data that can be trusted, not on a suspect value from a stray source. Those two things together are what make a notification mean something.

What the alert contains matters too. An alert that only says something happened forces the investor to work out for themselves what and why - which brings back part of the very effort the product was meant to remove. So the notification carries context straight away: which company, which condition, which values met it. The point is that after reading a single email a person knows enough to decide whether the matter is even worth pursuing further.

The biggest enemy of a product like this is alert fatigue. A handful of notifications that turn out to be irrelevant is enough for a user to start ignoring them reflexively - and then they miss the one that mattered too. That is why we deliberately favor fewer but more relevant: better for TickerFlow to speak up rarely, with every message carrying weight, than to be chatty and therefore unheard. It is a product decision as important as any rule in the engine.

Because in the end a product like this sells one thing: trust in its own silence. The user has to be able to assume that if TickerFlow sent nothing, nothing important happened - and that if it did send something, it is worth a look. Building something that can be relied on in that way is far harder than simply sending emails when one number crosses another.

Notifications that arrive on time

The channel the signals arrive through is email - and that too is a choice, not an accident. A notification about an opportunity on the market has to reach the investor where they already look, without forcing them to keep yet another app open or to watch a separate screen. Email is everywhere, it is durable, and it is easy to return to later.

Deliverability, though, is an engineering problem in its own right here. A notification that lands in spam or arrives late is just as worthless as one never sent. Making sure the emails go out punctually after the close and genuinely reach the inbox is work nobody thinks about until it fails - and for a product whose entire promise is to let people know at the right moment, it cannot fail.

The web app

Beyond the notifications, TickerFlow has a web app where the rest happens: defining and organizing thresholds, reviewing watched companies, checking what triggered a given alert and why. Choosing the web rather than a mobile app follows from how people actually work with a tool like this - configuring a strategy is more comfortable on a larger screen, unhurried, than on the move on a phone.

The interface is designed so that configuration is understandable for an investor, not only for an engineer. Setting a condition, assigning it to companies, seeing how it would behave on data - all of it is meant to lead a person by the hand, because a threshold set by mistake is either a missed opportunity or a false alarm. The product is only as good as it is easy to correctly tell it what to watch for.

An important part of the app is being able to check why a given alert appeared. Trust in notifications grows when they can be verified: seeing which condition was met, on what data, and at what moment. Transparency is a function of trust here - an investor who once checks that an alert was justified will react without hesitation next time, because they know the product does not fire blindly.

The knowledge base

We also gave the product a knowledge base of over fifty chapters. It is not a marketing add-on but part of the same idea: a tool that helps react to signals is worth as much as the understanding of why a given signal matters. An investor who knows where the rule of watching volume came from, or how to read a break of a level, sets better thresholds and makes better decisions than someone who only clicks around the interface.

Writing and organizing such a base is a body of work in itself, but it fits the same philosophy as the rest of the product: move the burden from the user to the tool. Where it can, automation and data do that; where a human decision is needed, it is done by knowledge presented in an understandable form, in the place where it happens to be needed.

Livermore's rule about volume is a good example here: the alert itself will say that volume rose, but it is a chapter of the knowledge base that explains why that is worth watching in the first place and how not to confuse confirmation with a trap. Tool and knowledge work together - one catches the moment, the other helps make sense of it. A product that gives a signal without context teaches clicking; a product that gives both teaches better decisions.

The knowledge base also plays a role at the first contact with the product. Someone just starting out does not always know what condition makes sense to set - and there a short chapter explaining a given strategy is the difference between a deliberate first threshold and random clicking. Good documentation shortens the road from signing up to the first well-aimed alert, and it is that first well-aimed alert that convinces someone it is worth staying.

Reliability: a run that cannot fail silently

There is one kind of failure a product like TickerFlow cannot afford to pass over in silence: the silent kind. If the daily run does not execute, or executes on incomplete data, and nobody notices, users simply will not get the alerts they should - and will not even know it. The absence of a notification looks identical whether nothing happened or the system failed. That is the most dangerous scenario, because it undermines trust in the product's silence, which is its very essence.

So we treated reliability as a feature, not an assumption. The run has to execute every trading day, and if something goes wrong - a source fails, data comes in incomplete, processing crashes - it has to be known and acted on, rather than letting silence pretend to be normality. Watching the watcher matters here as much as watching the market itself.

In practice this means we watch not only the market but the run itself: whether it executed in the expected window, whether it fetched data from every source, whether the numbers coming out fall within sensible bounds. When something is off, the signal reaches the team before it reaches - or rather fails to reach - the user. Silence towards the user is fine only when it is intended; silence caused by an unnoticed failure is exactly what this monitoring exists to prevent.

When something does fail, what counts is how quickly it can be put right without harm. A run that can be safely repeated on the missing data as soon as a source returns means that an evening's fault does not have to turn into a lost day of signals. The ability to catch up calmly is as important as avoiding failures - because failures happen anyway, and the difference is whether they leave permanent gaps behind.

What this build shows about how we work

Sending an email when one number crosses another is an afternoon's work. Doing it every trading day across thousands of instruments, on data nobody controls, with a bill that stays smaller than the revenue and a layer that catches the junk before it becomes a false alert - that is where the months go.

Two questions were answered before any code was written: what the data actually costs at seven thousand instruments, and what happens on the evening a source quietly lies. Both threatened the economics rather than the schedule, which is why neither could be left until halfway through. Verification then fell to a pair of eyes that had never seen the pipeline's internals, because in a data product the defects sit precisely where its builder was certain nothing could go wrong.

Data products are notoriously underestimated, because from the outside they look simple. "It is just alerts when a price crosses a level" sounds like a weekend of work - until you add multiple sources, cost, quality, adjustments for corporate actions, scale and reliability. Being able to see that hidden difficulty up front, rather than in the middle of the project, is part of what separates delivering such a product from getting stuck in it.

What generalises here is not stock alerts. It is the discipline of building on data you do not own: sourcing it from more than one place, paying for it deliberately, distrusting it by default, and noticing when the system has gone quiet for the wrong reason. Any product whose value comes from outside data lives or dies on those four things.

What we would tell another team

Before starting anything whose value rests on outside data - alerts, monitoring, any product that reacts to the world - these five are worth knowing.

These five are the reason a data product costs more than it looks like it should. None of them is visible in a demo, all of them are visible in the invoice and the support inbox, and every one is cheaper to design for than to discover.

Frequently asked questions

Is TickerFlow your own product, or did you build it for a client?

It is our own. We came up with it, designed it, built it and shipped it ourselves. We show it because it is proof of what we deliver, and we build for clients the same way.

Could you build a product based on external data sources?

Yes. TickerFlow combines multiple market-data sources and watches their cost and quality, and the same approach works for any product whose value comes from outside data.

How do you handle the cost of querying paid data sources?

We design what the system asks for, when and how often, so it fetches only what is needed, never pays twice for the same thing and never polls a source more than the data warrants. At the scale of thousands of instruments that is a condition of the product existing, not an add-on.

How do you make sure the product does not run on bad data?

We build a layer that distrusts source data by default: it sanity-checks values, compares them across sources and flags anomalies. We would rather withhold an alert based on a suspect value than send one that turns out to be a data error.

Do you build large-scale daily batch processing?

Yes. Every day after the close TickerFlow processes data for nearly seven thousand instruments and over a million historical records, inside the window in which notifications still have value.

Do we own the code and the accounts?

Yes. You own the code, the repositories and the accounts. We can hand everything over to your in-house team whenever you need it, with no lock-in.

Have a product where data is the heart of it?

We build data-driven products - from the sources, through cost and quality, to the interface and the notifications. A 30-minute call is enough to tell you what yours realistically takes.

Book a call
← Back to all work