Modules and Components

Our architecturally significant requirements workbook in hand, we are confident we have clear enough understanding of the problem to start building our high-level architecture.

Our goal now will be to map requirements to modules and components, explore possible architecture patterns and descend into details on critical points.

This is a long step, as we will build the bulk of the design, so I decided to split this step into multiple posts:

  1. Modules and components (this post).
  2. Exploring patterns.
  3. Critical points.

Modularizing the requirements

Modules overview

We will start with arranging our requirements as a set of modules. Each modules shall be responsible for one requirement, or one group of requirements. For instance, Cryptomate shall be able to open, cancel and monitor orders on trading platforms: a trading element would be in order.

Here are the modules I have identified:

Cryptomate module diagram
Module Diagram
Module Responsibility
Auditing Writes down auditing trails.
Control endpoint Authenticates and authorizes user requests. Manages strategies according to user directives.
Market history Provides random-access to past market events.
Notification Sends notifications based on user-defined rules.
Real-time market Provides access to real-time market events.
Strategy evaluator Runs user-defined business logic.
Strategy persistence Persists strategy state so it can be recovered.
Trading Controls orders placed by the system. Provides events related to orders.
Modules and responsibilities table

As usual, if you found I missed one, please tell me.

Component allocations

The way these modules get instantiated at run-time is interesting, to better understand the allocation mechanisms that will be needed:

Module Allocation Selected By
Auditing static, single configuration
Control endpoint static, single configuration
Market history static, single configuration
Notification static, single configuration
Real-time market dynamic, multiple strategy
Strategy evaluator dynamic, multiple strategy
Strategy persistence static, single configuration
Trading dynamic, multiple strategy
Component allocation table

Where static means the component is allocated on startup and destroyed at shutdown, while dynamic means allocations and de-allocations can happen during normal life of the system. Multiple allocations are the components that will have several instances coexisting during the life of the system. For instance, the system might connect to several markets at once.

Lastly, the third column details where the knowledge of what and how to instantiate components lives. In Cryptomate, it may either be statically configured within the configuration file, or dynamically decided by currently running strategies. This means both process will probably be complex enough to mandate a specific builder module.

We will therefore add the following modules to the list:

Module Responsibility
Configuration builder Instantiates and initializes statically-allocated components from a configuration description (either a file or a data-structure).
Strategy builder Instantiates or trigger the instantiation of components required to start a strategy. This includes the required bookkeeping to shut them down upon stopping the strategy.
Modules and responsibilities table

Event flow overview

Since market events will drive most of our logic, and trading is inherently very time-sensitive, now is a good time to picture how incoming market events will flow through our system, from market data providers all the way to outgoing trading orders:

Market event flow overview
Market event flow overview. Modules not taking a direct part in trading events are omitted.

We will be mindful of both ensuring the critical path has reasonable latency, and side processing do not introduce spurious delays.

Conclusion

This concludes our initial pass of identifying key Cryptomate modules. This is not set in stone yet, but this should be enough for us to design our high-level architecture.

So let's now explore architecture patterns we could use to structure those modules into an actual design.