Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/trading-algorithm-assessment.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public Action evaluate(SimpleAlgoState state) {

var totalOrderCount = state.getChildOrders().size();

//make sure we have an exit condition...
//make sure we have a we have an xit condition...
if (totalOrderCount > 20) {
return NoAction.NoAction;
}
Expand All @@ -37,6 +37,7 @@ public Action evaluate(SimpleAlgoState state) {

final var option = activeOrders.stream().findFirst();


if (option.isPresent()) {
var childOrder = option.get();
logger.info("[ADDCANCELALGO] Cancelling order:" + childOrder);
Expand All @@ -53,4 +54,8 @@ public Action evaluate(SimpleAlgoState state) {
return new CreateChildOrder(Side.BUY, quantity, price);
}
}
//@Override
//public long evaluate(SimpleAlgoState state, long size) {
// return 0;
//}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

public interface AlgoLogic {
Action evaluate(final SimpleAlgoState state);
// long evaluate(SimpleAlgoState state, long size);
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ public Action evaluate(SimpleAlgoState state) {
}

}
}
// @Override
//public long evaluate(SimpleAlgoState state, long size) {
// return 0;
//}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,34 @@
import org.slf4j.LoggerFactory;

import static codingblackfemales.action.NoAction.NoAction;

// declating SniperAlgoLogic class which implements AlgoLogic interface
public class SniperAlgoLogic implements AlgoLogic {

// creating a logger for SniperAlgoLogic class to log info
private static final Logger logger = LoggerFactory.getLogger(SniperAlgoLogic.class);

@Override
public Action evaluate(SimpleAlgoState state) {

// logging information that the algo has started
logger.info("[SNIPERALGO] In Algo Logic....");

// converting order book into a string format
final String book = Util.orderBookToString(state);

// logging the current state of order book
logger.info("[SNIPERALGO] Algo Sees Book as:\n" + book);

// retrieving the best ask price (the lowst price seller is willing to accept) from the order book
// state.getAskAt(0) represents best or lowest price in the market known as fatTuch
final AskLevel farTouch = state.getAskAt(0);

//take as much as we can from the far touch....
//setting the quantity and price for this order
long quantity = farTouch.quantity;
long price = farTouch.price;

//until we have three child orders....
// algo checks how many child orders it currently has in the market.
// if theres fewer 5, it will create more.
if (state.getChildOrders().size() < 5) {
//then keep creating a new one
logger.info("[SNIPERALGO] Have:" + state.getChildOrders().size() + " children, want 5, sniping far touch of book with: " + quantity + " @ " + price);
Expand All @@ -40,4 +47,18 @@ public Action evaluate(SimpleAlgoState state) {
return NoAction;
}
}
// @Override
//public long evaluate(SimpleAlgoState state, long size) {
// return 0;
//}
}
// goal: sniper algo aims to "snipe" the best ask price, so tryig to buy as much as possible at the lowest price(the best ask)
// until it has 5 child orders.
// flow:
// 1. logs the current state of the order book.
// 2. retrieves the best ask price.
// 3. if fewer than 5 chld orders exists, it creates a new buy order at the best ask price for the available quantity.
// 4. if 5 or more child orders exist, it does not hing.

// this algo follows a "sniping" strategy, where it aggressively tries to buy at the best available price on the ask side
// until it reaches a treshold of 5 active orders.
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ public interface SimpleAlgoState {
public List<ChildOrder> getActiveChildOrders();

public long getInstrumentId();


}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
import org.agrona.concurrent.UnsafeBuffer;
import org.junit.Assert;
import org.junit.Test;
// import uk.co.real_logic.sbe.ir.generated.MessageHeaderDecoder;
// import uk.co.real_logic.sbe.ir.generated.MessageHeaderEncoder;
// import messages.marketdata.BookUpdateEncoder;
// import messages.marketdata.BookUpdateDecoder;


import java.nio.ByteBuffer;

// import static com.sun.org.apache.xml.internal.serializer.utils.Utils.messages;


public class EncodingDecodingTest {

private final MessageHeaderDecoder headerDecoder = new MessageHeaderDecoder();
Expand All @@ -31,14 +39,14 @@ public void encodingDecoding() throws Exception {
encoder.instrumentId(123L);

encoder.askBookCount(3)
.next().price(100l).size(101l)
.next().price(90l).size(200l)
.next().price(80l).size(300);
.next().price(100L).size(101L)
.next().price(90L).size(200L)
.next().price(80L).size(300);

encoder.bidBookCount(3)
.next().price(110l).size(100)
.next().price(210l).size(200)
.next().price(310l).size(300);
.next().price(110L).size(100)
.next().price(210L).size(200)
.next().price(310L).size(300);

encoder.instrumentStatus(InstrumentStatus.CONTINUOUS);
encoder.source(Source.STREAM);
Expand Down
53 changes: 53 additions & 0 deletions algo-exercise/getting-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# MyAlgoLogic Trading Algorithm

## Overview

`MyAlgoLogic` is a trading algorithm designed to interact with a simulated market environment, making decisions to place buy and sell orders based on defined constraints. It manages an order book, handles market data changes, and dynamically updates based on predefined price limits and order management rules.

This repository includes:
- **Algorithm Logic** (`MyAlgoLogic`): Core trading logic with buy, sell, and cancel strategies.
- **Unit Tests** (`MyAlgoTest`): Isolated tests that simulate tick data to verify the algorithm's buy/sell and cancel logic.
- **Back Test** (`MyAlgoBackTest`): End-to-end backtesting that integrates with a mock market environment to validate overall behavior, including order fills and profit calculation.

## Project Structure

- **MyAlgoLogic.java**: Core algorithm logic implementing buy, sell, and cancel strategies.
- **MyAlgoTest.java**: Unit tests for isolated testing of the algorithm's behavior under controlled tick data.
- **MyAlgoBackTest.java**: Comprehensive backtest, simulating a live trading environment with order fills and profit evaluation.
- **AbstractAlgoTest.java** and **AbstractAlgoBackTest.java**: Base classes providing test infrastructure, including market simulation, tick data, and sequencing.

## Algorithm Features

### Key Logic
- **Buy Logic**: Places buy orders if the current market ask price is within a defined `priceLimit`.
- **Sell Logic**: Places sell orders if the market bid price exceeds a predefined `sellLimit`.
- **Cancel Logic**: Cancels active orders incrementally if the `clearActiveOrders` flag is enabled or `maxOrders` limit is reached.

### Constraints and Parameters
- **Price Limits**: Defines `priceLimit` for buy orders and `sellLimit` for sell orders.
- **Order Management**: Limits active orders to `maxOrders` and manages incremental cancellations when needed.
- **Quantity Per Order**: Each order is placed with a fixed quantity (`quantity`).

## Testing Overview

### Unit Tests (`MyAlgoTest`)
Tests the algorithm’s logic in isolation, ensuring:
- **Buy Logic Test**: Verifies buy orders are only placed when conditions match `priceLimit`.

### Backtests (`MyAlgoBackTest`)
Simulates the algorithm in a live market environment, validating:
- **Order Fills**: Checks if expected quantities are filled.
- **Order Status**: Confirms correct categorisation of partially and fully filled orders.
- **Profit Calculation**: Evaluates profit and verifies non-negative outcomes.

## Getting Started

1. **Run Unit Tests**:
```bash
mvn test -Dtest=MyAlgoTest
2. **Run Back Tests**:
```bash
mvn test -Dtest=MyAlgoBackTest

Happy Testing!

Loading