Building an Event Aggregation and Analysis System: A Practical Guide
This article presents a practical architecture for automating the collection, cleaning, classification, quantification, and alerting of fragmented market-moving information. It walks through a five-layer pipeline design, provides Python code samples for multi-source ingestion, deduplication, event classification, feature calculation, and impact scoring, and shares engineering lessons on idempotency, observability, data quality validation, and compliance. Readers will learn how to turn a manual weekly-news-summary workflow into a traceable, extensible system that lets humans focus on final value judgments.
1. Background: Why Manual Aggregation Falls Short
Every weekend, investors and researchers face a highly repetitive task: compiling a week’s worth of incremental information scattered across different channels—newly released policy documents from regulators, unusual moves in commodity prices, shifts in overseas central bank rate expectations, and macroeconomic data releases—into a structured summary, and then deriving a plan for the next stage. This work has three typical pain points:
- Fragmented sources with heterogeneous formats. Policy information is mostly long-form text, market information is mostly structured numbers, and expectation information (such as the rate-hike probabilities implied by interest rate derivatives) sits somewhere in between. Unified processing is expensive.
- High timeliness requirements. The weight of an event’s impact decays quickly over time. Get the news half a day late, and the strategic value may already be largely gone.
- Long judgment chains prone to omissions. From “event occurrence” to “impact assessment” to “action recommendation,” any manual link in between is easy to miss. For example, focusing only on the price change itself while ignoring synchronous changes in underlying drivers such as inventory and freight costs leads to attribution bias.
A more engineering-oriented approach is therefore to codify this chain into an automated system: let machines handle collection, cleaning, classification, quantification, and alerting, while people focus on final value judgments. Below is a practical reference design.
2. Overall Architecture: A Five-Layer Pipeline
The system can be split into five layers, each with a single responsibility and clear interfaces:
┌───────────────────────────────────────────┐│ Presentation: daily report generation / ││ dashboards / real-time alert push │├───────────────────────────────────────────┤│ Analysis: event classification / impact ││ scoring / correlation attribution │├───────────────────────────────────────────┤│ Processing: text cleaning / dedup / entity ││ and numeric extraction │├───────────────────────────────────────────┤│ Ingestion: adapter-pattern multi-source ││ access / scheduled dispatch │├───────────────────────────────────────────┤│ Storage: document store (text) + time- ││ series store (market metrics) │└───────────────────────────────────────────┘
Three core design principles:
- Decouple ingestion from analysis. Adding a new information source only requires implementing one adapter and does not affect any downstream logic, keeping extension cost near zero.
- Separate text and numeric storage. Policy documents and news bodies fit a document database for full-text search; metrics such as prices, probabilities, and inventories fit a time-series database for range statistics and retrospective analysis.
- End-to-end traceability. Each event retains its raw snapshot, cleaned text, classification labels, and scoring rationale, so you can fully reconstruct “why an alert was or was not triggered at the time”—a prerequisite for continuous tuning.
3. Core Module Design and Code Examples
3.1 Multi-Source Ingestion and a Unified Data Model
Different channels have very different scraping methods, but once inside the pipeline they should converge to a unified structure. The adapter pattern is recommended to isolate the differences:
from dataclasses import dataclassfrom typing import Protocol@dataclassclass RawEvent:source: str # source tag: policy / market / expectation / macrotitle: strbody: strpublished_at: str # ISO8601 timestampfp: str # content fingerprint for deduplicationclass SourceAdapter(Protocol):def fetch(self) -> list[RawEvent]:"""Each source implements a unified pull interface"""...
A two-tier scheduling strategy is recommended: high-frequency sources (market quotes, expectation probability data) polled at minute-level intervals; low-frequency sources (policy documents, monthly macro data) polled hourly or daily, avoiding unnecessary request pressure and ban risk.
3.2 Cleaning and Deduplication
The same event is often reported repeatedly across multiple channels. Deduplication has two steps:
- Exact dedup: compute a hash of the normalized body; discard if the fingerprint matches.
- Near dedup: compute SimHash on the title and first paragraph; treat a Hamming distance below the threshold as the same event, keep the earliest source, and record the number of channels that forwarded it—forwarding热度 itself can serve as a feature for later scoring.
import hashlib, redef normalize(text: str) -> str:text = re.sub(r"\s+", "", text)return text.lower()def fingerprint(text: str) -> str:return hashlib.sha256(normalize(text).encode("utf-8")).hexdigest()
3.3 Event Classification: Rules First, Models as Fallback
Referring to the common section structure of a “weekend news roundup,” events can first be divided into four categories: policy, market, meetings and expectations, and macro data. In the cold-start phase, keyword rules alone can achieve usable precision; after launch, keep collecting misclassified samples, then introduce a classification model to cover the parts the rules miss:
EVENT_RULES = {"policy": ["opinion", "action", "deployment", "plan", "title"],"market": ["closed up", "closed down", "intraday", "weekly", "inventory", "freight"],"expectation": ["rate meeting", "interest rate", "probability", "maintain", "hike"],"macro": ["year-over-year", "month-over-month", "value added", "retail", "investment"],}def classify(title: str, body: str) -> str:text = title + body[:500]scores = {k: sum(text.count(w) for w in ws)for k, ws in EVENT_RULES.items()}best = max(scores, key=scores.get)return best if scores[best] > 0 else "other"
Two engineering notes: first, for multi-topic text (for example, a document that both lays out industrial direction and mentions financial support measures), allow a list of labels rather than a single label, with downstream scoring by label separately; second, regularly track the “other” share of the rule classifier and the accuracy and recall of manual sampling, as the basis for deciding whether to upgrade to a model.
3.4 Market Feature Calculation and Driver Attribution
Market events should not look only at “how much it rose,” but at the driver structure. Taking commodity prices as an example, features worth continuously computing include: interval returns (weekly and monthly change), volatility (standard deviation of returns over the past 20 days), and synchronous changes in driver factors such as inventory levels and freight costs relative to price.
import pandas as pddef calc_features(df: pd.DataFrame) -> dict:df = df.sort_values("date")last = df["close"].iloc[-1]return {"weekly_chg": last / df["close"].iloc[-5] - 1,"monthly_chg": last / df["close"].iloc[-21] - 1,"vol_20d": df["close"].pct_change().rolling(20).std().iloc[-1],}
A configuration example: when the system detects that a commodity’s weekly gain exceeds 6% and monthly gain exceeds 10%, while the inventory indicator is at a five-year low and freight costs are surging in tandem, it should flag this as a “supply-driven rally,” distinct from pure sentiment swings—precisely the automated realization of attribution logic such as “geopolitical premium + low inventory,” and a key step to avoid “looking only at price change, not at driver structure.”
3.5 Impact Scoring and Tiered Alerting
The scoring function can be split into three factors: category weight × time freshness × quantitative strength:
from datetime import datetimeWEIGHTS = {"policy": 0.9, "expectation": 0.8,"macro": 0.7, "market": 0.6, "other": 0.3}def impact_score(evt: dict, now: datetime) -> float:base = WEIGHTS.get(evt["category"], 0.3)hours = (now - datetime.fromisoformat(evt["published_at"])).total_seconds() / 3600freshness = max(0.0, 1 - hours / 48)strength = min(1.0, abs(evt.get("strength", 0.5))) # map change/probability shift to 0~1return round(base * (0.5 + 0.3 * freshness + 0.2 * strength), 3)if impact_score(evt, datetime.now()) >= 0.7:alert(evt) # push and write to the daily report candidate queue
Tiered alerting is recommended: push immediately above 0.9; include in the same-day daily report at 0.7–0.9; keep in storage for the record only at 0.5–0.7. Thresholds are not fixed and should be recalibrated periodically based on historical false-positive and false-negative rates.
4. Engineering Best Practices
- Idempotency and retries. Use the content fingerprint as the idempotency key for ingestion tasks, and use exponential backoff for retries—avoiding duplicate writes while preventing request storms against target channels.
- Observability. Connect the pipeline to logging services and monitoring alerts, focusing on three metric classes: per-source ingestion success rate, classifier “other” share, and sudden spikes in alert volume. Whether using self-built components or general-purpose capabilities such as logging, monitoring alerts, and message queues offered by cloud platforms like Baidu AI Cloud, the key goal is the same: make every missed or false alert attributable and fixable.
- Data quality validation. Validate numeric fields for range and sudden changes; for example, when a daily change exceeds a historical percentile, mark it “pending verification” rather than triggering an alert directly, preventing dirty data from polluting downstream judgments.
- Positioning of summary generation. A large model can be introduced to generate weekly report drafts from aggregated events, but its output must be positioned as a “draft”: factual numbers must be checked back against the structured database, and conclusions involving action direction should retain a human confirmation step, forming a “machine draft + human final” double safeguard.
- Compliance and boundaries. System output is information organization and quantitative prompting, not investment advice; when provided externally, attach a clear disclaimer and manage data source authorization and copyright to avoid legal risk.
5. Summary
A “weekend news roundup + action strategy” is essentially an information-processing pipeline: ingestion → cleaning → classification → quantification → judgment. Once the first four stages are engineered and automated, human effort can be concentrated on the final stage of value judgment. The five-layer architecture and code skeleton given in this article are enough to support a minimum viable version starting from “one information source, one alert rule,” and then, as asset-class coverage and strategy complexity grow, evolve into a complete event analysis system with multiple sources, multiple assets, and multiple strategies.
