From ed9da0570f8f81b184cae533eee8d2d52a1b883e Mon Sep 17 00:00:00 2001 From: Peter Dekkers Date: Wed, 26 Jul 2023 06:50:46 +0200 Subject: [PATCH] Added doc --- .../kotlin/org/roboquant/perf/Performance.kt | 28 +++++----- .../kotlin/org/roboquant/http/WebServer.kt | 52 +++++++++++-------- .../roboquant/strategies/NoSignalStrategy.kt | 2 +- 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/roboquant-perf/src/main/kotlin/org/roboquant/perf/Performance.kt b/roboquant-perf/src/main/kotlin/org/roboquant/perf/Performance.kt index 91d9b524d..cfe90f325 100644 --- a/roboquant-perf/src/main/kotlin/org/roboquant/perf/Performance.kt +++ b/roboquant-perf/src/main/kotlin/org/roboquant/perf/Performance.kt @@ -33,7 +33,9 @@ import kotlin.system.exitProcess import kotlin.system.measureTimeMillis /** - * Simple fast strategy + * Simple fast strategy. + * + * Not realistic, but with minimal overhead to ensure we can measure the performance of the engine and not the strategy. */ private class FastStrategy(private val skip: Int) : Strategy { @@ -57,27 +59,29 @@ private class FastStrategy(private val skip: Int) : Strategy { } /** - * Fast feed + * Fast feed. + * + * Not realistic, but with minimal overhead to ensure we can measure the performance of the engine and are not + * impacted by the feed. */ -private class FastFeed(val nAssets: Int, val events: Int) : Feed { +private class FastFeed(nAssets: Int, val events: Int) : Feed { private val assets = mutableListOf() private val start = Instant.parse("2000-01-01T00:00:00Z") + val actions = ArrayList(nAssets) val size = nAssets * events init { repeat(nAssets) { assets.add(Asset("TEST-$it")) } + val data = doubleArrayOf(100.0, 101.0, 99.0, 100.0, 10000.0) + for (asset in assets) { + val action = PriceBar(asset, data) + actions.add(action) + } } override suspend fun play(channel: EventChannel) { repeat(events) { - val actions = ArrayList(nAssets) - val open = 100.0 + 10 * (it / events) - val data = doubleArrayOf(open, open + 1.0, open - 1.0, open, 500.0) - for (asset in assets) { - val action = PriceBar(asset, data) - actions.add(action) - } channel.send(Event(actions, start + it.millis)) } } @@ -90,8 +94,7 @@ private class FastFeed(val nAssets: Int, val events: Int) : Feed { * outside events like virus scanners. * * The main purpose is to validate the performance, throughput and stability of the back test engine, not any particular - * feed, strategy or metric. So the used feed and strategy are optimized for this test and not something you would - * normally use. + * feed, strategy or metric. So the used feed and strategy are optimized for this test and not realistic at all. */ private object Performance { @@ -177,6 +180,7 @@ private object Performance { val jobs = ParallelJobs() repeat(backTests) { jobs.add { + // use lower channel capacity to limit memory bandwidth val roboquant = Roboquant(getStrategy(skip), logger = SilentLogger(), channelCapacity = 3) roboquant.runAsync(feed) } diff --git a/roboquant/src/main/kotlin/org/roboquant/http/WebServer.kt b/roboquant/src/main/kotlin/org/roboquant/http/WebServer.kt index 95e08bb8d..b7ec0c8f4 100644 --- a/roboquant/src/main/kotlin/org/roboquant/http/WebServer.kt +++ b/roboquant/src/main/kotlin/org/roboquant/http/WebServer.kt @@ -68,29 +68,37 @@ private class WebMetric : Metric { override fun toString(): String { val acc = account ?: return "Not yet run" + val summary = listOf( + listOf("name", "value"), + listOf("last update", acc.lastUpdate), + listOf("events", events), + listOf("actions", actions), + listOf("buying power", acc.buyingPower), + listOf("equity", acc.equity), + listOf("open positions", acc.positions.size), + listOf("open orders", acc.openOrders.size), + listOf("closed orders", acc.closedOrders.size), + listOf("trades", acc.trades.size), + ) + return """ -
-

summary

-

events: $events

-

actions: $actions

-

buying power: ${acc.buyingPower}

-

equity: ${acc.equity}

+

summary

+ ${summary.toTable()} + +

cash

+ ${acc.cash} + +

positions

+ ${acc.positions.lines().toTable()} + +

open orders

+ ${acc.openOrders.lines().toTable()} + +

closed orders

+ ${acc.closedOrders.lines().toTable()} -

cash

- ${acc.cash} - -

positions

- ${acc.positions.lines().toTable()} - -

open orders

- ${acc.openOrders.lines().toTable()} - -

closed orders

- ${acc.closedOrders.lines().toTable()} - -

trades

- ${acc.trades.lines().toTable()} -
+

trades

+ ${acc.trades.lines().toTable()} """.trimIndent() } @@ -163,7 +171,7 @@ class WebServer(port: Int = 8000, username: String, password: String) { private fun detailsRun(run: String): String { val result = StringBuilder() val info = runs.getValue(run) - result.append("

${run}

") + result.append("

${run}

") result.append(info.metric.toString()) result.append("
Back".trimIndent()) return String.format(template, result) diff --git a/roboquant/src/main/kotlin/org/roboquant/strategies/NoSignalStrategy.kt b/roboquant/src/main/kotlin/org/roboquant/strategies/NoSignalStrategy.kt index 2485f0a1e..ff57f0fd3 100644 --- a/roboquant/src/main/kotlin/org/roboquant/strategies/NoSignalStrategy.kt +++ b/roboquant/src/main/kotlin/org/roboquant/strategies/NoSignalStrategy.kt @@ -21,7 +21,7 @@ import org.roboquant.feeds.Event /** * Strategy that doesn't generate any signals. This is especially useful if you develop your Strategy as * a Policy (for example, when you require access to the Account). In that case, the NoSignalStrategy just serves as - * a pass through and all logic can be handled by the policy. + * a pass-through and all logic can be handled by the policy. * * ## Example * ```