-
Notifications
You must be signed in to change notification settings - Fork 8
Traders and Indicators
The project contains multiple traders implementations, they are used to test the market simulator and experiment new strategies. They receive Order, Transaction or indicator data from the fetchers, the BackLoop or the indicator generators and send an order to the exchange when certain conditions are met.
###Traders
####Simple Trader The Simple trader periodically sends market orders to the exchange, the frequency of the orders is set in the constructor. It is intended to generate order executions to increase transactions volume.
####SOBI Trader The Static Order Book Imbalance (SOBI) trader maintains a copy of the MarketSimulator’s order books using delta orders and periodically checks a condition on the spread of a certain amount of bids and asks to produce an order. At each period, the trader computes the volume-weighted average price of the top of a certain amount of quartiles of the bid and ask order books bi and si. Then it applies the following algorithm to decide if an order is sent:

the SOBI constructor parameters are the amount of quartiles, the theta constant, the order volume V, the price deta P and the condition verification frequency.
####VWAP Trader The Volume-Weighted Average Price (VWAP) trader generates orders periodically when a certain condition is met. During each period, it stores the transaction prices. At the end of the period, a typical price multiplied by the sum of the transactions volume (TPV) is computed. This value is added to the cumulative TPV and divided by the cumulative volume to produce the VWAP.

If the trading price is greater than the VWAP, a market ask order is sent to the MarketSimulator, otherwise a market bid order is sent.
####Double Crossover Trader The Double Crossover trader monitors two moving averages of different periods, It sends a buy or sell signal when the two indicators cross. When the short MA crosses the other one from below, a market bid order is sent to the MarketSimulator. Conversely, when the short MA crosser the long one from above, a market ask order is sent. The trader’s constructor requires an order volume.
####Double Envelope Trader The Double envelope trader monitors the data from a single moving average. It computes two values that are each slightly above and below the actual MA by a factor alpha. When the current price crosses the upper bound, a market ask order is sent to the MarketSimulator. When the current price falls below the lower bound, a market bid order is sent to the Marketsimulator. This trader’s constructor parameters are the order volume and the alpha factor.
####Arbitrageur The Arbitrageur receives Transactions and OHLC data from multiple Exchanges and computes their price differences. When a certain price difference has been reached between markets, the Arbitrageur sends a market ask order to the one with the lowest price and a market bid order to the one with the highest price.
###Indicators
Many trading strategies rely on indicators instead of raw transactions prices or order books data. The project contains moving average indicators which take Open-High-Low-Close (OHLC) values as input. The OHLC Indicator generates OHLC values for a tick size in milliseconds passed in the constructor. If there are no transactions for a given time frame, an OHLC with all values set to the previous close value is generated. The MaIndicator superclass takes a period size in the constructor which corresponds to the amount of OHLCs it uses to compute the moving average. The project contains a simple moving average and a exponentially weighted moving average implementations defined in the SmaIndicator and EmaIndicator classes. To implement a moving average, a class needs to extends MaIndicator and override the computeMa() method.
The example below is the implementation of the EMA indicator:
case class EMA(override val value: Double, override val period: Int)
extends MA(value: Double, period: Int)
class EmaIndicator(val period: Int) extends MaIndicator(period) {
var previousEma: Double = 0.0
def computeMa: EMA = {
val alpha = 2 / (1 + 2 * period)
previousEma = (alpha * values.head.close) +
previousEma * (1 - alpha)
EMA(previousEma, period)
}}