Following One Stock Request Through the Pipeline

zhulinsen/daily_stock_analysis becomes easier to understand when we follow one request instead of touring its features. The specific question is causal: what happens between submitting a stock symbol and receiving a saved decision dashboard? Tracing that path lets the reader see where market meaning is established, where evidence is assembled, where the model contributes, and where the surrounding system can still constrain the result.

The important consequence is that generation is only one stage. A report can contain a polished conclusion because the pipeline prepared a context, because the model followed a JSON contract, and because post-processing accepted, adjusted, or rejected parts of the result. The sequence is therefore part of the project’s meaning.

The run begins by deciding what the request means

A stock symbol is not yet a complete analysis instruction. Before asking for a conclusion, the system needs to know which market the symbol belongs to, what time it is in that market, and whether the request is for an ordinary stock or a target with a different capability profile. It also needs a reference date for the daily data that can legitimately be reused.

The pipeline establishes a market-phase context at the start of a single-stock run. That context records the market, market-local time, session date, effective daily-bar date, whether the market is trading or open, whether the current bar may be partial, and any warnings produced by the calendar layer. The result is passed forward as structured context rather than being left as an assumption hidden inside a later prompt. A model that sees “today” without knowing whether the session is still in progress can easily describe an observation as a completed fact; the early phase step is meant to prevent that category error.

The pipeline can also load a daily market summary for the relevant market when that feature is enabled. This is not the same as replacing the stock analysis with a market report. It is a way to give the individual decision a surrounding environment: a stock signal may deserve a more conservative interpretation when the broader market context is explicitly marked high risk or cooling. The distinction matters because the project keeps the daily market context as a small, low-sensitivity input rather than passing an entire market-review payload through every path.

Once the target has a market and time frame, the run resolves a display name. For ordinary symbols, the data layer can provide the name without first making a full realtime request. That small ordering choice avoids turning a missing quote into an identity failure. An analysis can still identify its subject even if the preferred quote service is unavailable.

The next step is realtime data, when it is enabled. The pipeline asks its data-source manager for a unified quote rather than making every downstream component understand every provider’s response shape. A returned quote may contain a price, change percentage, volume-related fields, valuation fields, and source metadata. If every realtime source fails, the pipeline logs the condition and continues with historical closing data where possible. That is a graceful continuation, not a claim that the historical close is equivalent to a current quote.

Chip distribution is fetched separately. It can enrich the context with profit ratio, average cost, concentration, and a qualitative chip status, but it is not allowed to become a single point of failure for the whole analysis. If this optional input is absent, later layers can mark it missing or unsupported instead of inventing a value. This is the first example of a general rule: each input has its own failure boundary, while the overall run has a separate success boundary.

Evidence is assembled before generation

After the initial quote and chip steps, the pipeline gathers the evidence that gives a dashboard more substance than a single price comparison. It may aggregate fundamentals, attach board or market-structure context, compute a trend result from stored daily history, search for recent intelligence, and load locally persisted intelligence. These operations do not all have the same status. Some can be unavailable for a market; some can fail for this request; some can return a partial result; and some may be skipped because the feature is not configured.

The trend calculation illustrates the handoff between stored data and current observation. The pipeline reads a historical window from storage and passes it to a technical analyzer. When a realtime quote is available, the current observation may be overlaid on the historical frame so moving averages and related technical fields can reflect the current session. That overlay is useful precisely because it is marked as realtime and estimated rather than silently replacing the completed historical record. The trend result then becomes an artifact that both the traditional analyzer and the Agent path can use.

Intelligence is another distinct input channel. In the ordinary path, the search service can perform several dimensions of research, including current news, company announcements, risks, and earnings expectations. For US stocks, an optional social-sentiment service can add another context. The pipeline can also load locally persisted intelligence and append it to the context. These sources answer different questions from the technical history: they may explain a catalyst, a regulatory risk, an earnings event, or a change in market attention. Their presence should not be inferred from the fact that the model later writes a sentence about sentiment; the pipeline keeps track of whether evidence was actually retrieved.

Only after these inputs are available does the system read its storage-based analysis context and create an enhanced context. The enhanced form combines the basic historical view with the name, realtime fields, chip information, trend result, fundamentals, phase, market context, and other applicable metadata. It is the working material for generation. The point is not to make a giant undifferentiated prompt. It is to bring together inputs that were fetched or computed under different rules while retaining enough provenance to interpret them.

This is where the AnalysisContextPack enters. In the current design, the pack builder is deliberately zero-fetch. It does not call a provider, database, search API, or Agent tool a second time. It assembles the artifacts the pipeline already has into named blocks and produces two different projections: a low-sensitivity summary for the model and a public overview for later inspection. The order protects against a common architectural failure: building a new “context system” that quietly repeats requests, applies different status rules, and creates a second source of truth.

The model-facing summary can say that the quote is available, that the technical block is partial because it has a realtime overlay, or that news is missing. It does not need to expose every raw news item, trend payload, or secret to communicate that limitation. The public overview can show block status, source, warnings, missing reasons, counts, and quality information without becoming a raw dump of the prompt. The pipeline therefore sends the model a shaped description of its evidence conditions, not just a bag of numbers.

The whole sequence can be represented as follows:

sequenceDiagram participant C as Caller participant P as Analysis pipeline participant S as Data and intelligence services participant X as Context pack builder participant G as LLM or Agent participant Q as Guardrails participant H as History store participant D as DecisionSignal index C->>P: Submit symbol and run options P->>P: Resolve market and phase P->>S: Request quote, history, trend, fundamentals, and intelligence S-->>P: Return artifacts, sources, and limitations P->>X: Assemble enhanced context and pack X-->>P: Return model summary and public overview P->>G: Generate structured dashboard G-->>P: Return model output P->>Q: Normalize action and check phase and data quality Q-->>P: Return accepted or constrained result P->>H: Save report and optional context snapshot H-->>P: Return durable report identity P->>D: Best-effort extract downstream signal P-->>C: Return dashboard or task status

The diagram shows several ownership boundaries. The caller owns the request, not the meaning of the market data. The data services own retrieval and provider-specific adaptation. The context builder owns representation of already-collected artifacts, not fetching. The model or Agent owns a synthesis attempt. The guardrail layer owns deterministic checks and action adjustments. The history store owns durable report state, after which a downstream signal can point back to a saved report.

Generation is a middle stage, not the endpoint

The project has two broad generation paths that share this pipeline boundary. The traditional analyzer receives the enhanced context, intelligence content, and context-pack summary, then asks an LLM for a decision-dashboard JSON object. The Agent path receives the inputs that have already been prepared and can perform a staged analysis with specialized roles. In either case, the surrounding pipeline—not the model alone—decides when the result is ready to become an AnalysisResult.

The distinction between these paths is about how synthesis is performed, not about whether evidence handling matters. A traditional call may make the sequence look short: prepare prompt, receive JSON, parse it. An Agent run may involve several structured opinions and tool calls before the final synthesis. Yet both still need a subject, market phase, relevant inputs, a context representation, an output contract, and post-generation handling. The shared boundary is what keeps optional complexity from becoming a second definition of a valid report.

The traditional path makes the output contract especially visible. The model is asked for a core conclusion, score, trend prediction, operation advice, a three-state compatibility decision, a richer action, confidence, a data perspective, intelligence, a battle plan, and phase decision. The parser checks that the response contains a usable JSON object, normalizes action fields, and can retry when required content is missing if integrity checking is enabled. If the model returns text that cannot be parsed into the required structure, the system can produce a low-confidence best-effort result marked unsuccessful rather than quietly treating prose as a completed, durable report.

That behavior explains why the pipeline does not save history immediately after the model returns text. First it fills or normalizes fields that the rest of the application relies on. It may supply current price and change data from the context, normalize unavailable chip structure, fill missing price-position information when a supported fallback exists, and stabilize action semantics against technical or fundamental structure. It then applies phase-aware and daily-market-context guardrails. Only the resulting object is the candidate report.

These controls are not a hidden promise that the system knows the correct trade. They are limits on what the generated answer may claim. If core quote, daily-bar, or technical data is degraded, the result can be prevented from presenting high confidence. If the phase is premarket, non-trading, or unknown, an immediate intraday buy or sell formulation can be softened. If an intraday answer accidentally adopts the language of a completed postmarket recap, the wording can be replaced with a phase-safe alternative. The model remains responsible for interpretation, but the pipeline owns the conditions under which that interpretation is allowed to appear.

Failure is similarly staged. Search initialization can fail and leave the run without current intelligence. Realtime retrieval can fail and lead to historical-close analysis. Chip or fundamental enrichment can be missing, partial, unsupported, or explicitly failed while the technical and news paths continue. Historical context itself can be unavailable; in that case the pipeline creates a visibly data-missing context and may analyze only what remains, rather than manufacturing a daily bar. A generation backend can be unavailable or return invalid output, in which case the result is marked as a failure with low confidence. The phrase “fail open” therefore means “continue without hiding the limitation,” not “every degraded run is as good as a complete run.”

History and downstream indexing come last because they depend on a coherent report identity. A saved history record provides a durable reference for later inspection. The pipeline then best-effort extracts a DecisionSignal tied to that report. If signal extraction fails, the primary report need not be discarded; if history saving fails, the system logs the problem rather than pretending that the downstream signal exists. This ordering keeps the core result separate from an optional index of recommendations and prevents later consumers from pointing at a report that was never durably created.

The same separation protects the user from confusing a recommendation with execution. A dashboard can contain an action such as watch, buy, reduce, or sell, and a downstream signal can track that recommendation. Neither one places an order or changes a portfolio. The project’s pipeline is complete when it has produced and, where configured, saved and delivered an analysis artifact—not when a financial action has occurred.

Following the request end to end reveals the project’s strongest design claim. It does not claim that every source is fresh, every market has the same capabilities, or every model answer is correct. It claims a more limited but more defensible thing: the request passes through explicit stages where evidence, timing, model output, and action semantics can be inspected separately. The next question is what happens when the preferred data path breaks—and how the dashboard should communicate the difference between continuity, freshness, and capability.

References