Three months ago, I compared open-source frameworks for MOEX. Figured out what to choose. But the question remained: how does it all work inside?

You can read the docs. You can study the API. But real understanding comes only when you open the code and see the architecture.

So today isn’t about choosing a platform. It’s about what happens under the hood.

I analyzed the architecture of four popular open-source robots: Freqtrade, NautilusTrader, Hummingbot, and the microservices-based MBATS.

Conclusion: despite different languages and goals, patterns repeat. If you understand them, you can design your own system right from the start.

Layered Architecture: The Foundation

Most trading robots follow a 5-layer architecture:

Layer 5: Communication Layer     <- Telegram, Web UI, API
Layer 4: Strategy Layer          <- Trading logic
Layer 3: Execution & Risk        <- Orders, risk management
Layer 2: Data Processing         <- Indicators, normalization
Layer 1: Data Ingestion          <- Exchange connections

Layer 1: Data Ingestion

Task: Get data from the exchange and deliver it to the system.

Freqtrade uses ccxt to support 100+ exchanges without writing separate connectors. NautilusTrader has its core in Rust with streaming up to 5 million rows per second.

Takeaways: Use adapters, unify interfaces, separate data retrieval from processing.

Layer 2: Data Processing

Task: Transform raw prices into indicators, ML features, signals.

NautilusTrader writes all indicators in Rust with bounded memory. FreqAI integrates ML (LightGBM, PyTorch, Reinforcement Learning) directly into Freqtrade.

Takeaways: Separate feature generation from inference, cache indicator calculations, use bounded buffers.

Layer 3: Execution & Risk Management

Task: Take a β€œbuy” decision and turn it into a real order with risk controls.

Freqtrade includes dynamic position sizing and overtrading protection. Microservices architectures use Smart Order Routing (SOR) as a separate service.

Layer 4: Strategy Layer

Task: Determine when to buy and sell.

Freqtrade completely separates strategy from execution. NautilusTrader uses the Actor Model for event-driven strategies with microsecond reactions.

Layer 5: Communication & Monitoring

Freqtrade has built-in Telegram bot, REST API, and Web UI. Professional systems export metrics to Prometheus and visualize in Grafana.

Design Patterns for Trading Robots

1. Event Sourcing

Saves every state change as an event. Crucial for auditing, debugging, and regulatory compliance.

2. CQRS (Command Query Responsibility Segregation)

Separates reads from writes. The Event Store handles writes; a separate database with pre-computed aggregates handles queries.

3. Microservices Architecture

MBATS splits the system into independent services communicating via Kafka/RabbitMQ. Each service scales independently. Different languages for different tasks.

4. Actor Model

NautilusTrader and Hummingbot use it. Each actor has independent state, communicates via messages. No shared state means no race conditions.

Checklist: Designing Your Own Robot

  1. Start with a monolith β€” don’t jump to microservices prematurely
  2. Separate layers from day one β€” even in a monolith
  3. Design for testing β€” dependency injection, mocks, abstractions
  4. Add observability from day one β€” logs, metrics, tracing
  5. Plan persistence β€” save all orders, positions, settings, events
  6. Switch to microservices only when: >100 instruments, HFT, team >3 developers

Common Mistakes

  1. Everything in one file β€” impossible to test, reuse, or maintain
  2. No exchange abstractions β€” adding a second exchange means changing code in 50 places
  3. No logging or metrics β€” you won’t understand why the robot traded at 3 AM
  4. Synchronous code β€” use async (aiohttp, not requests) for exchange APIs
  5. Ignoring backpressure β€” use bounded queues to prevent memory growth

Conclusions

Key principles:

  1. Separate layers β€” data, processing, strategy, execution, communication
  2. Use adapters β€” don’t write exchange logic in strategies
  3. Design for testing β€” dependency injection
  4. Add observability β€” logs, metrics, tracing
  5. Start with a monolith β€” don’t over-engineer prematurely

Architecture determines how far you’ll go. Spaghetti code works for a month. Proper architecture β€” for years.


Useful links: