Skip to content

Commit

Permalink
First stab at harmonizing Strategy + Trader 3
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaron committed Jun 30, 2024
1 parent 4111dcd commit 68f10d5
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ internal class TaSamples {
internal fun customPolicy() {

/**
* Custom SignalConverter that extends the FlexConverter and captures the ATR (Average True Range) using the TaLibMetric. It
* then uses the ATR to set the limit amount of a LimitOrder.
* Custom SignalConverter that extends the FlexConverter and captures the ATR (Average True Range) using the
* TaLibMetric. It then uses the ATR to set the limit amount of a LimitOrder.
*/
class SmartLimitSignalConverter(private val atrPercentage: Double = 200.percent, private val atrPeriod: Int) :
class SmartLimitConverter(private val atrPercentage: Double = 200.percent, private val atrPeriod: Int) :
FlexConverter() {

// use TaLibMetric to calculate the ATR values
Expand Down Expand Up @@ -127,7 +127,7 @@ internal class TaSamples {

val feed = RandomWalk.lastYears(5)
val strategy = EMACrossover.PERIODS_12_26
strategy.signalConverter = SmartLimitSignalConverter(atrPeriod = 5)
strategy.signalConverter = SmartLimitConverter(atrPeriod = 5)
val account = run(feed, EMACrossover.PERIODS_12_26)
println(account)
}
Expand Down
12 changes: 6 additions & 6 deletions roboquant/src/main/kotlin/org/roboquant/orders/TimeInForce.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.roboquant.orders
import java.time.Instant

/**
* Time in force (TiF) allows you to put an expiration or fill signalConverter on an order. It determines how long an order
* Time in force (TiF) allows you to put an expiration or fill policy on an order. It determines how long an order
* remains active before it expires. There are two triggers that can determine if an order expires:
*
* - How much *time* has passed since the order was first placed.
Expand All @@ -31,7 +31,7 @@ import java.time.Instant
interface TimeInForce

/**
* Good Till Cancelled signalConverter. The order will remain active until fully filled or is cancelled.
* Good Till Cancelled policy. The order will remain active until fully filled or is cancelled.
* In practice, most brokers allow such orders to remain active for a 60-90 day period, so not indefinitely.
*
* @property maxDays the maximum number of days an order stays valid, default is 90 calendar days.
Expand All @@ -47,7 +47,7 @@ class GTC(val maxDays: Int = 90) : TimeInForce {
}

/**
* Good Till Date signalConverter. The order will remain active until fully filled or a specified date.
* Good Till Date policy. The order will remain active until fully filled or a specified date.
*
* @property date
* @constructor Create new GTD tif
Expand All @@ -62,7 +62,7 @@ class GTD(val date: Instant) : TimeInForce {
}

/**
* Immediate or Cancel (IOC) signalConverter. An immediate or cancel order is an order to buy or sell an asset that attempts
* Immediate or Cancel (IOC) policy. An immediate or cancel order is an order to buy or sell an asset that attempts
* to execute all or part immediately and then cancels any unfilled portion of the order.
*
* @constructor Create new IOC tif
Expand Down Expand Up @@ -93,8 +93,8 @@ class DAY : TimeInForce {
}

/**
* Fill Or Kill (FOK) signalConverter. A Fill or Kill signalConverter is to be executed immediately at the market or a specified price
* or cancelled if not filled.
* Fill Or Kill (FOK) policy. A Fill or Kill policy is to be executed immediately at the market or a
* specified price or cancelled if not filled.
*
* @constructor Create a new FOK tif
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.roboquant.strategies

import org.roboquant.brokers.Account
import org.roboquant.feeds.Event
import org.roboquant.orders.Instruction

/**
*
* @property signalConverter SignalConverter
* @constructor
*/
abstract class SignalStrategy(var signalConverter: SignalConverter = FlexConverter()) : Strategy {

override fun create(event: Event, account: Account): List<Instruction> {
val signals = generate(event)
return signalConverter.convert(signals, account, event)
}

abstract fun generate(event: Event): List<Signal>

}


/**
* A SignalConverter is responsible for creating [Orders][Instruction] based on the [Signals][Signal] generated by a
* strategy. Besides, turning signals into orders, a signalConverter should also take care of:
*
* * signal conflicts: for example, receive both a SELL and BUY signal for the same asset at the same time
* * order management: for example, how to deal with open orders
* * portfolio construction: for example, re-balancing of the portfolio based on some pre-defined risk parameters
* * risk management: for example, limit exposure to certain sectors
*
* Please note that a broker which receives the orders that a SignalConverter created, might not support all the different
* order types.
*/
fun interface SignalConverter {

/**
* Convert the received [signals] into orders, based also on the latest state of the [account] and
* the last known [event].
*
* @param signals the list of [signals][Signal] generated by the strategy
* @param account the account state at a point in time
* @param event the market data
* @return a list of orders
*/
fun convert(signals: List<Signal>, account: Account, event: Event): List<Instruction>


}

0 comments on commit 68f10d5

Please sign in to comment.