Incremental Decomposition of a Live Runtime System

Modern systems rarely begin with perfect architecture.

Most real systems evolve from:

  • a working prototype,
  • an operational script,
  • a single service,
  • or a growing runtime loop.

The real engineering challenge is not building a perfect greenfield design.

The real challenge is:

evolving a live operational system safely without breaking it.

That process is what I call:

Incremental Decomposition of a Live Runtime System

The Common Trap

Many developers eventually hit this moment:

“This service became too large.”

Then the dangerous ideas start:

  • “Let’s rewrite everything.”
  • “Let’s implement Clean Architecture.”
  • “Let’s rebuild using microservices.”
  • “Let’s move to CQRS/Event Sourcing.”

Most systems fail here.

Why?

Because:

  • operational behavior is already working,
  • runtime assumptions already exist,
  • hidden coupling already formed,
  • production logic already evolved organically.

Large rewrites usually introduce:

  • instability,
  • regressions,
  • unclear ownership,
  • endless refactor cycles.

A Better Approach

Instead of rewriting:

progressively extract responsibilities.

One boundary at a time.

One stable contract at a time.

One operational behavior at a time.


Real Example — Trading Runtime Evolution

A trading bot often starts like this:

Program.cs
-> fetch data
-> generate signal
-> validate risk
-> place order
-> update state
-> log everything

At first this is fine.

But eventually:

  • stop-loss logic grows,
  • portfolio rules grow,
  • runtime recovery appears,
  • execution tracking appears,
  • reconciliation becomes necessary.

Now the single service becomes:

operationally dense.


The Wrong Move

The wrong response is:

“Rewrite the entire platform.”

The correct response is:

“What responsibility can be safely extracted next?”

The Decomposition Pattern

A mature decomposition sequence often looks like:

Step 1 — Separate Signal Generation

Strategy
decides

TradingService
orchestrates

Step 2 — Separate Risk Governance

RiskEngine
validates

TradingService
gathers runtime context

Step 3 — Separate Execution

ExecutionService
places broker orders

Step 4 — Separate Lifecycle Tracking

TradeLifecycleService
records audit trail

Step 5 — Separate Runtime State

PositionStateService
manages runtime transitions

Step 6 — Separate Recovery

RecoveryService
reconciles broker/runtime state

Step 7 — Separate Runtime Coordination

TradingRuntimeService
owns orchestration loop

The Key Insight

Notice something important:

No rewrite occurred.

The runtime stayed operational the entire time.

That is critical.

Because architecture should evolve:

under operational pressure.

Not in isolation.


Why Incremental Decomposition Works

This approach provides:

1. Operational Stability

The system continues running while architecture improves.


2. Smaller Blast Radius

Each extraction changes only one responsibility.

Failures become easier to isolate.


3. Better Runtime Understanding

You discover real system boundaries from:

  • runtime behavior,
  • operational pain,
  • scaling pressure,
  • recovery needs.

Not from theoretical diagrams.


4. Cleaner Ownership

Eventually the system becomes:

Runtime Coordinator
orchestrates

Governance Services
validate

Workflow Services
coordinate

Execution Services
execute

Recovery Services
reconcile

At that point:

  • reasoning improves,
  • testing improves,
  • extensibility improves,
  • future capabilities emerge naturally.

The Most Important Engineering Skill

Most developers learn:

  • frameworks,
  • patterns,
  • syntax.

Far fewer learn:

controlled evolution of operational systems.

That skill matters more in real engineering environments.

Because most enterprise systems are not rewritten.

They evolve.


When To Stop Refactoring

This is equally important.

Eventually you reach:

diminishing returns.

At that point:

  • stop extracting services,
  • stop renaming abstractions,
  • stop chasing “perfect architecture.”

Instead:

  • run the system,
  • observe failures,
  • validate recovery,
  • analyze logs,
  • study runtime behavior.

Operational pressure should guide the next evolution.


Final Thought

Good architecture is not:

  • maximum abstraction,
  • maximum patterns,
  • or maximum complexity.

Good architecture is:

clear responsibility boundaries that evolved safely under real operational conditions.

That is how live runtime systems mature professionally.

Building a Minimal Yet Serious Trading Platform Architecture

Introduction

Most trading bot tutorials start with a single console application and slowly evolve into unmaintainable complexity:

  • trading logic mixed with broker code
  • logging scattered everywhere
  • global runtime state
  • no lifecycle tracking
  • no operational telemetry
  • no execution governance

At the other extreme, many architecture discussions immediately jump into:

  • microservices
  • CQRS
  • event sourcing
  • distributed actors
  • Kubernetes
  • enterprise-level abstraction layers

Neither extreme is ideal for an MVP trading platform.

This article walks through the architecture evolution of a lightweight but serious trading system built with:

  • C#
  • .NET
  • Alpaca API
  • Azure-ready deployment patterns

The goal was simple:

Build an architecture strong enough to evolve into a SaaS trading platform later, without overengineering the MVP.


The Core Philosophy

The architecture intentionally favors:

  • practical layering
  • operational clarity
  • explainable execution
  • incremental evolution
  • execution-aware telemetry
  • runtime correctness
  • low ceremony

The system intentionally avoids:

  • premature distributed systems
  • unnecessary abstractions
  • architecture for architecture’s sake
  • enterprise-pattern overload

The focus is:

Build only what real runtime pressure requires.


Final Architecture

Tanolis.Trading.Console

Tanolis.Trading.Core.Domain

Tanolis.Trading.Core.Services

Tanolis.Trading.Infrastructure


Dependency Structure

Console

↓ references

Core.Services

↓ references

Core.Domain

Infrastructure

↓ references

Core.Services

↓ references

Core.Domain

Additionally:

Console

↓ references

Infrastructure


Visual Architecture Shape

Console


Layer Responsibilities

Tanolis.Trading.Console

Purpose:

  • runtime host
  • execution scheduler
  • startup/bootstrap
  • configuration loading
  • dependency wiring

Examples:

  • Program.cs
  • execution timers
  • appsettings loading
  • runtime startup

The console project should NOT contain:

  • trading logic
  • broker implementation logic
  • persistence logic
  • lifecycle management

Tanolis.Trading.Core.Domain

Purpose:

  • business meaning
  • trading vocabulary
  • lifecycle models
  • domain constants
  • runtime state models

Examples:

  • TradeRecord
  • TradeSignal
  • BotState
  • SymbolState
  • ExitReasons
  • TradeActions
  • LogEvents
  • LogLevel
  • LogSources

The domain layer intentionally remains independent of:

  • Alpaca SDK
  • Azure SDKs
  • SQL Server
  • runtime hosting
  • logging implementations
  • persistence implementations

This keeps the business concepts clean and portable.


Tanolis.Trading.Core.Services

Purpose:

  • execution orchestration
  • trading workflows
  • lifecycle coordination
  • risk management
  • application contracts
  • runtime coordination

Examples:

  • TradingService
  • StateService
  • TradeJournalService
  • SmaStrategy
  • RuntimeContext
  • IBroker
  • ILogService

Suggested internal structure:

Core.Services

Contracts

IBroker.cs

ILogService.cs

Configuration

TradingConfig.cs

AlpacaConfig.cs

Models

BrokerOrderResultDto.cs

OrderDto.cs

Trading

TradingService.cs

Strategies

SmaStrategy.cs

State

StateService.cs

Journaling

TradeJournalService.cs

Runtime

RuntimeContext.cs

Core.Services acts as the orchestration and application behavior layer.


Tanolis.Trading.Infrastructure

Purpose:

  • external integrations
  • broker connectivity
  • logging implementations
  • operational integrations
  • persistence implementations

Examples:

  • AlpacaBroker
  • LogService
  • Azure integrations
  • future SQL implementations
  • future Table Storage implementations

Infrastructure implements application contracts defined by Core.Services.

Example:

publicclassAlpacaBroker : IBroker

and:

publicclassLogService : ILogService

This creates clean dependency inversion while keeping the architecture lightweight.


Ports and Adapters Direction

One interesting architectural observation was that the platform naturally evolved toward:

Ports and Adapters

without intentionally overengineering for it.

Current mapping:

LayerRole
Core.Servicesports/contracts
Infrastructureadapters
Core.Domainbusiness concepts
Consolecomposition root

This created a clean separation between:

  • business intent
  • execution orchestration
  • external implementations
  • runtime hosting

without introducing unnecessary complexity.


Operational Telemetry Philosophy

One major architectural decision was treating logs as:

operational decision telemetry

instead of simple debug output.

This changed the entire design approach.

The system now tracks:

CategoryPurpose
Signal telemetrywhy signals occurred
Execution telemetrywhy trades executed or were blocked
Risk telemetrygovernance decisions
Lifecycle telemetrytrade continuity
Runtime telemetryoperational health

Examples:

TradeBlocked | DailyLossLimit

TradeBlocked | OpenOrderExists

TradeSkipped | SidewaysMarket

StateReconciled | Clearing stale state

This dramatically improves:

  • debugging
  • strategy analysis
  • operational trust
  • SaaS observability
  • future analytics

Symbol-Scoped Runtime State

One of the most important architectural evolutions was moving from:

global runtime state

to:

symbol-scoped runtime state

Originally the bot stored:

one EntryPrice

one ActiveTradeId

one LastTradeTime

for ALL symbols.

This worked initially but became a serious correctness problem once the bot traded:

  • AAPL
  • MSFT
  • NVDA

simultaneously.

The solution was introducing:

Dictionary<string, SymbolState>

inside:

BotState

Each symbol now maintains:

  • isolated trade lifecycle
  • isolated cooldowns
  • isolated stop-loss state
  • isolated reconciliation state
  • isolated PnL tracking

This was one of the most important runtime architecture corrections in the platform.


Runtime Metadata and Trade Lifecycle Tracking

The platform also evolved into execution-aware lifecycle tracking.

The system now tracks:

IdentifierPurpose
SessionIdbot runtime instance
CycleIdexecution loop iteration
TradeIdtrade lifecycle
OrderIdbroker execution

This enables:

  • execution tracing
  • operational diagnostics
  • auditability
  • lifecycle analytics
  • future distributed execution support

without prematurely implementing distributed systems.


Why Minimal Architecture Matters

The biggest lesson from this architecture journey was:

Minimal architecture does NOT mean weak architecture.

The platform now supports:

  • multi-symbol execution
  • isolated runtime state
  • execution governance
  • structured telemetry
  • lifecycle tracing
  • broker abstraction
  • operational reconciliation
  • future cloud hosting
  • SaaS evolution

while still remaining:

  • understandable
  • lightweight
  • maintainable
  • incremental

Future Direction

The current architecture is intentionally designed to evolve gradually toward:

  • Azure Container Apps
  • Azure Table Storage telemetry
  • SQL Server + EF Core persistence
  • Web API exposure
  • Blazor dashboards
  • analytics and reporting
  • multi-user SaaS support
  • distributed runtime workers

The key principle is:

Only evolve architecture when real operational pressure justifies it.


Final Thoughts

A successful MVP architecture is not the one with the most patterns.

It is the one that:

  • survives growth
  • remains understandable
  • supports operational visibility
  • evolves incrementally
  • avoids unnecessary complexity

This trading platform architecture intentionally focused on:

practical engineering over architectural theater

And that balance turned out to be far more valuable than prematurely chasing enterprise complexity.

Understanding My Trading Bot Like a 12-Year-Old

Imagine a Robot Watching the Stock Market

Think about a robot sitting in front of giant TV screens all day watching companies like:

  • AAPL (Apple)
  • MSFT (Microsoft)
  • NVDA (NVIDIA)

People around the world buy and sell these company shares every second.

The robot’s job is simple:

“Only buy or sell when the situation looks good.”

That robot is called a trading bot.


What Is a Stock?

A stock is a tiny piece of ownership in a company.

If a company does well:

  • more people want to buy it
  • price usually goes up 📈

If a company struggles:

  • people sell it
  • price usually goes down 📉

Example:

CompanyPrice
Apple$280
Microsoft$520
NVIDIA$170

These prices move all day long.


What Does the Trading Bot Actually Do?

The bot checks stock prices every few minutes and asks questions like:

  • Is the stock moving up?
  • Is the market too quiet?
  • Is the market too messy?
  • Is there a strong trend?

Then it decides:

DecisionMeaning
BUY“This may go up.”
SELL“This may go down.”
HOLD“Do nothing right now.”

Why HOLD Is Actually Smart

Many people think:

“A trading bot should trade all the time!”

But smart traders know:

Sometimes the best move is to WAIT.

Imagine playing soccer.

A bad goalie jumps at every ball.

A smart goalie waits for the right moment.

The bot is trying to be the smart goalie.


Understanding SMA (Simple Moving Average)

The bot uses something called:

SMA = Simple Moving Average

That sounds complicated, but it’s just an average.

Example:

If Apple prices were:

10, 12, 14, 16, 18

The average is:

14

The bot compares:

  • current price
  • average price

to understand the trend.


Example of a Trend

Upward Trend 📈

100 → 102 → 104 → 106

This means:

“People keep buying.”


Downward Trend 📉

106 → 104 → 102 → 100

This means:

“People keep selling.”


Understanding ATR (Volatility)

The bot also measures something called:

ATR = Average True Range

This tells the bot:

“How much is the stock moving around?”


Quiet Market Example

100 → 100.02 → 100.01

Very little movement.

The bot says:

“This market is sleepy.”


Active Market Example

100 → 103 → 98 → 105

Lots of movement.

The bot says:

“Now things are interesting!”


What Is “LowATR”?

Sometimes the bot logs this:

Reason: LowATR

That means:

“The stock is too quiet right now.”

The bot avoids trading in boring markets.


What Is “SidewaysMarket”?

Sometimes prices move like this:

100 → 101 → 100 → 101 → 100

No real direction.

This is called a sideways market.

The bot says:

“I can’t tell where this market wants to go.”

So it waits.


Why Waiting Is Important

Most beginner bots make this mistake:

BUY SELL BUY SELL BUY SELL

all day long.

That usually loses money because the market becomes noisy and confusing.

A better bot:

  • waits patiently
  • ignores weak signals
  • trades only when conditions improve

What Is Paper Trading?

Right now the bot uses:

fake money

through Alpaca.

This is called:

Paper Trading

It allows learning without risking real money.


What Happens During a Good Trade?

Imagine this happens:

  1. Apple starts moving strongly upward
  2. The bot sees a trend
  3. The bot buys
  4. Price continues upward
  5. The bot sells later
  6. Small profit earned

That is the goal.


What Happens During a Bad Trade?

Sometimes the bot is wrong.

Example:

  1. Bot buys
  2. Market suddenly drops
  3. Bot exits quickly
  4. Small loss only

This is why the bot has:

  • stop losses
  • risk rules
  • safety filters

Why the Logs Matter

The bot writes logs like:

LowATR
SidewaysMarket
NoConfirmation

This is like the robot explaining its thinking.

Instead of:

“Trust me.”

It says:

“I avoided this trade because the market looked weak.”

That’s important because humans can understand and improve the system.


What Is the Real Goal?

The goal is NOT:

be rich overnight

The real goal is:

make careful decisions automatically

This is similar to how professional trading firms work.


What Skills Are Being Learned?

Building a trading bot teaches:

  • programming
  • math
  • logic
  • automation
  • risk management
  • patience
  • decision making

It combines technology and business together.


The Most Important Lesson

A smart trading system is NOT:

always trading

A smart trading system is:

careful about WHEN it trades

And that is exactly what this trading bot is learning to do.

The world of honeybees

If you also think of yourself as useless, then you must read this…

The world of honeybees is one of nature’s most astonishing miracles, where every individual is busy performing a specific role. Inside this tiny hive operates a complex social system whose two most important figures are the queen and the drones. Their lives are so different that it is hard to believe they belong to the same species.

The queen bee is the heart of the colony, a monarch who lives among her subjects yet is so unique that she stands apart in every way. Her body is noticeably longer and more elegant than other bees, and when she moves inside the hive, worker bees surround her like guards protecting their queen. Interestingly, however, the queen is not born a princess. She comes from an ordinary egg, just like any worker bee.

The only difference is that when the colony needs a new queen, worker bees begin feeding certain larvae a special substance called “royal jelly.” This milky white food is so powerful that it changes the entire genetic destiny of the larva. A larva that might have become an ordinary worker instead becomes a queen. It is a masterpiece of nature’s chemistry: simply by changing the diet, a bee’s entire life, size, lifespan, and abilities are transformed.

One of the most fascinating chapters of the queen’s life is her mating flight, which happens in daylight rather than at night. When the queen matures, she leaves the hive only once in her lifetime for this purpose. She flies high into the sky, and drones chase after her. It becomes an extraordinary competition, with hundreds of male bees pursuing one queen, though only a few reach her. The queen mates with several drones in the air and stores their sperm inside her body, enabling her to lay millions of eggs over the next five years.

Now consider the story of the drones, perhaps among nature’s strangest creations. These male bees are born without a father. When the queen lays unfertilized eggs, they develop into drones containing only the mother’s genes. These bees are larger, have big eyes, and live carefree lives. They have no sting, do not make honey, do not collect pollen, and do not even gather their own food. Worker bees feed them, almost as if idle princes are being raised.

A drone’s entire life has only one purpose: to mate with a queen. But here lies the irony—any drone that succeeds dies immediately after mating because his reproductive organs remain inside the queen. Success itself leads to death. And the drones that fail in this competition do not fare much better.

When winter approaches and food becomes scarce, worker bees throw the lazy drones out of the hive. It is a harsh decision but necessary for the colony’s survival. The drones die from cold and hunger, while the workers and the queen survive the winter safely inside the hive.

This system is strange yet remarkably successful. A queen, who can live up to five years, lays more eggs daily than her own body weight. Imagine laying around two thousand eggs per day—one every few seconds—continuing for months. She releases special chemical signals that keep the entire colony united. If the queen dies or becomes weak, the colony realizes it within hours and immediately begins raising a new queen.

Though the drone’s story may seem tragic, their existence is just as essential as the queen’s. They bring genetic diversity to the colony. By mating with multiple drones, the queen ensures the next generation carries a mix of traits, improving resistance to diseases and increasing survival chances in different conditions.

Honeybees possess an astonishing ability that scientists call the “waggle dance.” When a worker bee finds a good source of flowers or food, she doesn’t simply bring honey back. Instead, she returns to the hive and performs a special dance.

Through this dance, she tells the other bees the direction of the food source, how far away it is, and how abundant it is. The angle of the dance indicates the direction relative to the sun, while the duration of the dance communicates the distance.

The most fascinating part is that bees also account for the movement of the sun. Even if the sun has shifted position, the bee still communicates the correct direction in her dance, as if she possesses both a natural compass and an internal clock.

In other words, this tiny insect uses a system involving mathematics, navigation, time calculation, and collective communication—one that has functioned for millions of years without any teacher or school.

Thus, within a tiny hive exists a complete kingdom: a queen who rules, thousands of hardworking workers serving the colony’s welfare, and drones who play a temporary but essential role in producing the next generation. This system has functioned for millions of years without law books, police, or armies—perhaps far more organized and successful than human societies.