Other Strategy Ports
Continuing the strategy port sub-series, we will now design the remaining ports.
Remaining ports are much simpler in their scope, and in the fact they do not manage dynamic subscriptions. They are setup at the start of execution, and stay essentially static.
We will review them quickly for completeness, but there is not much challenge in their design.
The role the history port is to provide the strategy module with past market data. It is used for three purposes:
- Backtesting strategies, by generating events from old market data.
- Advanced strategies can analyzing past events looking for statistic biases relevant to current market situation.
- Writing data from the market port, so it can be used for those purposes.
It is obvious from those purposes that the clients that read and write past data are completely uncorrelated. Following the interface segregation principle, this means we should have separate interfaces for reading and for writing.
In fact, we could arguably have two reading interfaces, given generating a stream of events and crunching statistics on the whole dataset have very different performance, feature and… interface implications. Yet I chose not to for now, knowing this will not matter until we have large amounts of data to crunch. At this point we can come back and upgrade the design.
Lastly, as the order book events are incremental updates, we must write a full copy regularly to serve as starting points for reconstitution.
Apart from this subtlety, the history port interfaces are straightforward.
The role of the notification port is to give external tools visibility on what happens within Cryptomate. This could be leveraged eg. to send visual updates to end users, emails notifications or charge accounts.
This is not much to be said, the interface consists of a single method that emits notifications to whatever the underlying adapter works with.
The role of the persistence port is to keep a trace of transient state so, in the event the system is restarted, running strategies may recover and resume from where they left off.
As strategies are not visible by this port, we shall use a memento approach: the persistence port will provide saving and restoring arbitrary data chunks, the meaning of which will only be known to client code.
It also needs a way to enumerate stored chunks so those can be used at startup. Relevant methods have been specified as an abstract class here.
This concludes the strategy port sub-series. It is an important milestone, as, if one remembers our architecture diagram, it means we have fully specified the trapezoids that pull our modules together:
Thus, we have well-defined boundaries with well-defined contracts insulating modules from each other.
We have successfully divided the project into meaningful parts, we will now start conquering them.