Skip to content

Commit

Permalink
Removed ref to priceAction
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaron committed Jun 24, 2024
1 parent b7a4a37 commit d46aff2
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 47 deletions.
23 changes: 22 additions & 1 deletion roboquant/src/main/kotlin/org/roboquant/brokers/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,35 @@ interface Account {
* Equity is defined as the sum of [cash] balances and the market value of the open [positions].
*/
val equity: Wallet
get() = cash + positions.values.marketValue
get() = cash + marketValue()

/**
* Unique set of assets hold in the open [positions]
*/
val assets: Set<Asset>
get() = positions.keys

/**
* Return the market value of the open positions, optionally filter by one or more asset.
*/
fun marketValue(vararg assets: Asset): Wallet {
return positions.filterValues { assets.isEmpty() || it.asset in assets }.values.marketValue
}

/**
* Return the unrealized PNL of the open positions, optionally filter by one or more asset.
*/
fun unrealizedPNL(vararg assets: Asset): Wallet {
return positions.filterValues { assets.isEmpty() || it.asset in assets }.values.unrealizedPNL
}

/**
* Return the realized PNL of the trades, optionally filter by one or more asset.
*/
fun realizedPNL(vararg assets: Asset): Wallet {
return trades.filter { assets.isEmpty() || it.asset in assets }.realizedPNL
}

/**
* Convert an [amount] to the account [baseCurrency] using last update of the account as a timestamp
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ class InternalAccount(override var baseCurrency: Currency) : Account {

val prices = event.prices
for ((asset, position) in positions) {
val priceAction = prices[asset]
if (priceAction != null) {
val price = priceAction.getPrice(priceType)
val priceItem = prices[asset]
if (priceItem != null) {
val price = priceItem.getPrice(priceType)
val newPosition = position.copy(mktPrice = price, lastUpdate = event.time)
positions[asset] = newPosition
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ object OrderExecutorFactory {
// register all the default included order handlers

// Single Instruction types
register<MarketOrder> { MarketOrderExecutor(it as MarketOrder) }
register<LimitOrder> { LimitOrderExecutor(it as LimitOrder) }
register<StopLimitOrder> { StopLimitOrderExecutor(it as StopLimitOrder) }
register<StopOrder> { StopOrderExecutor(it as StopOrder) }
register<TrailLimitOrder> { TrailLimitOrderExecutor(it as TrailLimitOrder) }
register<TrailOrder> { TrailOrderExecutor(it as TrailOrder) }

// Advanced order types
register<BracketOrder> { BracketOrderExecutor(it as BracketOrder) }
register<OCOOrder> { OCOOrderExecutor(it as OCOOrder) }
register<OTOOrder> { OTOOrderExecutor(it as OTOOrder) }
register<MarketOrder> { MarketOrderExecutor(it) }
register<LimitOrder> { LimitOrderExecutor(it) }
register<StopLimitOrder> { StopLimitOrderExecutor(it) }
register<StopOrder> { StopOrderExecutor(it) }
register<TrailLimitOrder> { TrailLimitOrderExecutor(it) }
register<TrailOrder> { TrailOrderExecutor(it) }

// Combined order types
register<BracketOrder> { BracketOrderExecutor(it) }
register<OCOOrder> { OCOOrderExecutor(it) }
register<OTOOrder> { OTOOrderExecutor(it) }

}

Expand All @@ -63,8 +63,9 @@ object OrderExecutorFactory {
factories.remove(T::class)
}

inline fun <reified T : Order> register(noinline factory: (Order) -> OrderExecutor) {
factories[T::class] = factory
inline fun <reified T : Order> register(noinline factory: (T) -> OrderExecutor) {
@Suppress("UNCHECKED_CAST")
factories[T::class] = factory as (Order) -> OrderExecutor
}


Expand Down
6 changes: 3 additions & 3 deletions roboquant/src/main/kotlin/org/roboquant/feeds/Feed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,12 @@ fun Feed.validate(
try {
while (true) {
val o = channel.receive()
for ((asset, priceAction) in o.prices) {
val price = priceAction.getPrice(priceType)
for ((asset, priceItem) in o.prices) {
val price = priceItem.getPrice(priceType)
val prev = lastPrices[asset]
if (prev != null) {
val diff = (price - prev) / prev
if (diff.absoluteValue > maxDiff) errors.add(Pair(o.time, priceAction))
if (diff.absoluteValue > maxDiff) errors.add(Pair(o.time, priceItem))
}
lastPrices[asset] = price
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import java.util.*

/**
* Base class that provides a foundation for data feeds that provide historic prices. It uses a sorted map to store
* for each time one or more PriceActions in memory.
* for each time one or more priceItems in memory.
*/
open class HistoricPriceFeed : HistoricFeed {

Expand Down
3 changes: 1 addition & 2 deletions roboquant/src/main/kotlin/org/roboquant/metrics/PNLMetric.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package org.roboquant.metrics

import org.roboquant.brokers.Account
import org.roboquant.brokers.unrealizedPNL
import org.roboquant.common.Asset
import org.roboquant.common.Timeframe
import org.roboquant.feeds.Event
Expand Down Expand Up @@ -89,7 +88,7 @@ class PNLMetric(private val priceType: String = "DEFAULT") : Metric {
if (equity.isNaN()) equity = account.equityAmount.value
val pnl = account.equityAmount.value - equity

val pnl2 = account.positions.values.unrealizedPNL
val pnl2 = account.unrealizedPNL()
val unrealizedPNL = pnl2.convert(account.baseCurrency, event.time).value

event.prices.values.forEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package org.roboquant.metrics

import org.roboquant.brokers.Account
import org.roboquant.brokers.unrealizedPNL
import org.roboquant.feeds.Event
import java.time.Instant

Expand Down Expand Up @@ -59,7 +58,7 @@ class ScorecardMetric : Metric {

val realizedPNL = pnl.sum()

val unrealizedPNL = account.positions.values.unrealizedPNL.convert(account.baseCurrency, event.time).value
val unrealizedPNL = account.unrealizedPNL().convert(account.baseCurrency, event.time).value
val equity = account.equity.convert(account.baseCurrency, event.time).value

val cash = account.cash.convert(account.baseCurrency, event.time).value
Expand Down
14 changes: 7 additions & 7 deletions roboquant/src/main/kotlin/org/roboquant/policies/FlexPolicy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -279,23 +279,23 @@ open class FlexPolicy(
val position = account.positions.getOrDefault(asset, Position.empty(asset))

// Don't create an order if we don't know the current price
val priceAction = event.prices[asset]
if (priceAction == null) {
val priceItem = event.prices[asset]
if (priceItem == null) {
log(signal, null, position, "no price")
continue
}

if (config.oneOrderOnly && account.openOrders.contains(asset)) {
log(signal, priceAction, position, "one order only")
log(signal, priceItem, position, "one order only")
continue
}

val price = priceAction.getPrice(config.priceType)
logger.debug { "signal=${signal} buyingPower=$buyingPower amount=$amountPerOrder action=$priceAction" }
val price = priceItem.getPrice(config.priceType)
logger.debug { "signal=${signal} buyingPower=$buyingPower amount=$amountPerOrder action=$priceItem" }


if (reducedPositionSignal(position, signal)) {
val order = createOrder(signal, -position.size, priceAction) // close position
val order = createOrder(signal, -position.size, priceItem) // close position
instructions.addNotNull(order)
} else {
if (position.open) continue // we don't increase position sizing
Expand All @@ -308,7 +308,7 @@ open class FlexPolicy(
if (size.isNegative && !config.shorting) continue
if (!meetsMinPrice(asset, price, time)) continue

val order = createOrder(signal, size, priceAction)
val order = createOrder(signal, size, priceItem)
if (order == null) {
logger.trace { "no order created time=$time signal=$signal" }
continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ abstract class PriceStrategy(private val priceType: String = "DEFAULT") :

override fun generate(event: Event): List<Signal> {
val signals = mutableListOf<Signal>()
for ((asset, priceAction) in event.prices) {
val price = priceAction.getPrice(priceType)
for ((asset, priceItem) in event.prices) {
val price = priceItem.getPrice(priceType)
val signal = generate(asset, price, event.time)
if (signal != null) signals.add(signal)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ abstract class SingleAssetStrategy(

override fun generate(event: Event): List<Signal> {
val result = mutableListOf<Signal>()
val priceAction = event.prices[asset]
if (priceAction != null) {
val signal = generate(priceAction, event.time)
val priceItem = event.prices[asset]
if (priceItem != null) {
val signal = generate(priceItem, event.time)
result.addNotNull(signal)
}
return result
Expand All @@ -46,10 +46,10 @@ abstract class SingleAssetStrategy(
* Subclasses need to be implemented this method. It will only be invoked if there is
* a price action for the asset available.
*
* @param priceAction
* @param priceItem
* @param time
* @return
*/
abstract fun generate(priceAction: PriceItem, time: Instant): Signal?
abstract fun generate(priceItem: PriceItem, time: Instant): Signal?

}
4 changes: 2 additions & 2 deletions roboquant/src/test/kotlin/org/roboquant/TestData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ internal object TestData {

fun usMarketOrder() = MarketOrder(usStock(), 10)

fun priceAction(asset: Asset = usStock()) = TradePrice(asset, 10.0)
fun priceItem(asset: Asset = usStock()) = TradePrice(asset, 10.0)

private fun priceBar(asset: Asset = usStock()) = PriceBar(asset, 10.0, 11.0, 9.0, 10.0, 1000.0)

fun time(): Instant = Instant.parse("2020-01-03T12:00:00Z")

fun event(time: Instant = time()) = Event(time, listOf(priceAction()))
fun event(time: Instant = time()) = Event(time, listOf(priceItem()))

fun event2(time: Instant = time()) = Event(time, listOf(priceBar()))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import org.roboquant.TestData
import org.roboquant.brokers.Account
import org.roboquant.brokers.Broker
import org.roboquant.brokers.FixedExchangeRates
import org.roboquant.brokers.marketValue
import org.roboquant.common.Amount
import org.roboquant.common.Asset
import org.roboquant.common.Config
Expand Down Expand Up @@ -94,7 +93,7 @@ internal class CashAccountTest {

account = update(broker, abc, 100, 40)
assertEquals(initial, account.equityAmount)
assertEquals(4_000.EUR.toWallet(), account.positions.values.marketValue)
assertEquals(4_000.EUR.toWallet(), account.marketValue())
assertEquals(6_000.EUR, account.buyingPower)

account = update(broker, abc, 75)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal class AssetFilterStrategyTest {

@Test
fun test() {
val action = TestData.priceAction()
val action = TestData.priceItem()
val strategy = AlwaysStrategy().filter(AssetFilter.all())
val event = Event(Instant.now(), listOf(action))
val signals = strategy.generate(event)
Expand All @@ -45,7 +45,7 @@ internal class AssetFilterStrategyTest {

@Test
fun test2() {
val action = TestData.priceAction()
val action = TestData.priceItem()
val event = Event(Instant.now(), listOf(action))
val asset = action.asset
val strategy = AlwaysStrategy().filter(AssetFilter.excludeSymbols(asset.symbol))
Expand All @@ -55,7 +55,7 @@ internal class AssetFilterStrategyTest {

@Test
fun test3() {
val action = TestData.priceAction()
val action = TestData.priceItem()
val strategy = AlwaysStrategy().filter { asset, _ ->
asset.symbol == "DUMMY"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal class SingleAssetStrategyTest {

private class MyStrategy(asset: Asset) : SingleAssetStrategy(asset) {

override fun generate(priceAction: PriceItem, time: Instant): Signal {
override fun generate(priceItem: PriceItem, time: Instant): Signal {
return Signal.buy(asset)
}

Expand Down

0 comments on commit d46aff2

Please sign in to comment.