
The project
I wanted to develop my skills using the professional tools that the industry uses to deliver their products. To accomplish that, I simply looked at many job descriptions and noted down what I would have to learn and then incorporate that into a fun project. I decided to build a simple Java-based trading client to execute algorithmic trades. Such Fun!
Project Function and Goals
- Tech Stack
- Application Flow
- Data Handling
- Scalability
- Goals
I also drew a quick sketch of what I wanted the UI to look like, which helped illustrate the features that I needed to implement.


To claim this project a success, I wanted it to be able to connect to a public trading API of your choosing and automatically execute trades by following simple in-built strategies. Also minimise the latency between receiving the data, calculating the strategy, and sending the trade order. Achieving this would be a great showing on my portfolio.
The Tech Stack
Each tool that I used and implemented tackles a certain problem for the development of this project. I did research on its suitability by answering 3 questions. How will it support my project? What makes it stand out? Lastly is it easy/quick to implement?
For example, I chose JavaFX as it allowed for quick development of the UI interface and is rich with tutorials and walkthroughs.
Here is a table listing the purpose of each tool in this project.
| Technology | Purpose |
| Maven | Manage the dependencies, build configurations and run automated testing. |
| JavaFX | Mature platform for UI development and supports plugins. |
| ChartFX | Library extension for JavaFX that supports financial charts. |
| Jackson Databind | Send and receive data in the JSON structure to and from APIs. |
| Apache HTTP Client | Easilly build http requests in parts and execute requests as a lambda function. |
| Log4J w/ SLF4J | Commonly used logging tool behind an abstracted framework for compatibility with other systems. |
| JUnit | Testing framework to minimise bugs and ensure working releases. |
| Mockito | Enhances tests by mocking classes for more granular testing. |
| Joda Money | Store, calculate and display currency with ease. Avoiding issues with calcualtions on floating points. |
| Github Actions | Automate the testing and packaging of the application for release. |
| CodeCov | Generate a report of the testing coverage to gain further insight into testing completeness. |
Development Process
Beginning
Middle
First Iteration of EventChannel
public void publish(Object data, AppEventType type) throws InterruptedException {
AppEvent event = new AppEvent(data, type);
events.put(event);
eventProcessor.submitTask(this::notifySubscribers);
}
public void subscribe(Consumer consumer) {
consumers.add(consumer);
}
private void notifySubscribers() {
AppEvent event = events.poll();
if (event == null) return;
for (Consumer consumer : consumers) {
consumer.processEvent(event);
}
}
Final Iteration of EventChannel
public void publish(Object data, AppEventType type, EventConsumer sender) throws InterruptedException {
events.put(new AppEvent(data, type, sender));
eventProcessor.submitTask(this::notifySubscribers);
}
public void connectToService(EventConsumer eventConsumer) {
EnumSet<AppEventType> subscribed = EnumSet.noneOf(AppEventType.class);
consumers.put(eventConsumer, subscribed);
}
public void subscribeToEvent(EventConsumer eventConsumer, AppEventType type) {
EnumSet<AppEventType> acceptedEvents = consumers.get(eventConsumer);
if (acceptedEvents != null) {
acceptedEvents.add(type);
}
}
private void notifySubscribers() {
AppEvent event = events.poll();
if (event == null) return;
for (var entry : consumers.entrySet()) {
EventConsumer eventConsumer = entry.getKey();
EnumSet<AppEventType> acceptedEvents = entry.getValue();
if (!acceptedEvents.contains(event.type())) continue;
if (event.sender() == eventConsumer) continue;
eventConsumer.processEvent(event);
}
}End
Challenges
try {
filePathTemp = AccountApiStore.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()
+ "accounts.json";
String absolutePath = new File(filePathTemp).getAbsolutePath();
}After
try {
filePathTemp = AccountApiStore.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
File tempFile = new File(filePathTemp);
if (filePathTemp.endsWith(".jar")) {
tempFile = tempFile.getParentFile();
}
filePathTemp = tempFile.getAbsolutePath() + File.separator + "accounts.json";
}Lessons Learned

- using a dependency manager – (Maven)
- UI development in MVC format – (JavaFX)
- Handling JSON based data – (Jackson Databind)
- testing framework – (JUnit + Mockito)
- logging tools – (Log4J + SLF4J)
- HTTP requests – (Apache HTTP)
- automated workflows – (GitHub Actions + CodeCov)