Skip to content

Model MultiPeriodKagiMRStrategyDemo

github-actions[bot] edited this page Oct 18, 2026 · 8 revisions

MultiPeriodKagiMRStrategyDemo — execution tutorial

All model results · Pinned source · Javadoc

What this example teaches

Using this example. Runs MultiPeriodKagiMRStrategySim using MRSimParamSP500 and inspects the resulting basket analysis and performance report. Basket construction and subsequent trading are separate stages; review their data windows before adapting the example.

Model and publication. Sparse mean-reverting portfolio construction motivates the basket search. The paper’s predictability criterion is not itself a trading return.

Implementation in this tutorial. MultiPeriodKagiMRStrategySim repeatedly combines selection and trading according to MRSimParamSP500, then exposes a PerformanceReport and basket diagnostics. Basket renewal, Kagi execution and the chosen universe are application settings; compare estimation windows with trade dates to avoid future information.

Verified execution record

Item Value
Status timeout
Run 39114006111
UTC publication 2026-10-18 09:11 UTC
Source commit 0097e73c040bdaaddac570e2fe694d9836b676ee
Data mode original main defaults
Exit code -15
Elapsed seconds 180.14
Time limit seconds 180
Maximum Java heap 1200m

The original main exceeded the configured execution limit; partial outputs are not a completed result.

Reproduce the calculation

Follow the repository setup for JDK 8, Maven credentials and an external NM license. From the repository root:

mvn -U -Dmaven.test.skip=true clean package
mvn exec:java -Dexec.mainClass=tech.nmfin.algoquant.demo.model.daspremont2008.MultiPeriodKagiMRStrategyDemo

The automated run uses scripts/ModelDemoRunner.java to initialize the external license before the unchanged main, save JFreeChart windows as PNGs, and exit after main returns. It uses an isolated working directory with the repository datasets/configuration linked in. Running directly may leave desktop windows open.

Observed output

This is an incomplete or blocked run. Output below is diagnostic or partial, not a verified strategy result.

09:06:54,077 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
09:06:54,077 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
09:06:54,077 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:file:/home/runner/work/algoquant-examples/algoquant-examples/target/lib/algoquant-dist-3.3.0-SNAPSHOT.jar!/logback.xml]
09:06:54,092 |-INFO in ch.qos.logback.core.joran.spi.ConfigurationWatchList@61a52fbd - URL [jar:file:/home/runner/work/algoquant-examples/algoquant-examples/target/lib/algoquant-dist-3.3.0-SNAPSHOT.jar!/logback.xml] is not of type file
09:06:54,640 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
09:06:54,641 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
09:06:54,648 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
09:06:54,653 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
09:06:54,685 |-INFO in ch.qos.logback.core.joran.action.TimestampAction - Using current interpretation time, i.e. now, as time reference.
09:06:54,686 |-INFO in ch.qos.logback.core.joran.action.TimestampAction - Adding property to the context with key="bySecond" and value="2026.10.18,09.06.54" to the LOCAL scope
09:06:54,686 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.rolling.RollingFileAppender]
09:06:54,689 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [FILE1]
09:06:54,694 |-INFO in ch.qos.logback.core.rolling.FixedWindowRollingPolicy@233c0b17 - Will use zip compression
09:06:54,695 |-WARN in ch.qos.logback.core.rolling.FixedWindowRollingPolicy@233c0b17 - Large window sizes are not allowed.
09:06:54,695 |-WARN in ch.qos.logback.core.rolling.FixedWindowRollingPolicy@233c0b17 - MaxIndex reduced to 21
09:06:54,697 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
09:06:54,698 |-INFO in ch.qos.logback.core.rolling.RollingFileAppender[FILE1] - Active log file name: log/algoquant.2026.10.18,09.06.54.log
09:06:54,698 |-INFO in ch.qos.logback.core.rolling.RollingFileAppender[FILE1] - File property is set to [log/algoquant.2026.10.18,09.06.54.log]
09:06:54,699 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
09:06:54,699 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
09:06:54,699 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [FILE1] to Logger[ROOT]
09:06:54,699 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
09:06:54,700 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@63d4e2ba - Registering current configuration as safe fallback point

09:06:55.297 [main] INFO  t.n.a.m.m.d.s.MultiPeriodKagiMRStrategySim,246 - there are 4 periods (period = P6M) in the interval [2013-01-01T00:00,2015-01-01T00:00): [2013-01-01T00:00, 2013-07-01T00:00, 2014-01-01T00:00, 2014-07-01T00:00]
09:06:55.312 [basket-precompute-1-thread-4] INFO  t.n.a.m.m.d.s.SimpleMRBasketProvider,197 - computing baskets at time 2013-07-01T00:00 (covPenalty=1.5E-4; inSamplePeriodForClustering=P10Y; inSamplePeriodForBasketSelection=P5Y; nBaskets=1; basketSize=5)
09:06:55.312 [basket-precompute-1-thread-2] INFO  t.n.a.m.m.d.s.SimpleMRBasketProvider,197 - computing baskets at time 2014-07-01T00:00 (covPenalty=1.5E-4; inSamplePeriodForClustering=P10Y; inSamplePeriodForBasketSelection=P5Y; nBaskets=1; basketSize=5)
09:06:55.312 [basket-precompute-1-thread-1] INFO  t.n.a.m.m.d.s.SimpleMRBasketProvider,197 - computing baskets at time 2013-01-01T00:00 (covPenalty=1.5E-4; inSamplePeriodForClustering=P10Y; inSamplePeriodForBasketSelection=P5Y; nBaskets=1; basketSize=5)
09:06:55.312 [basket-precompute-1-thread-3] INFO  t.n.a.m.m.d.s.SimpleMRBasketProvider,197 - computing baskets at time 2014-01-01T00:00 (covPenalty=1.5E-4; inSamplePeriodForClustering=P10Y; inSamplePeriodForBasketSelection=P5Y; nBaskets=1; basketSize=5)
09:06:55.327 [basket-precompute-1-thread-1] INFO  t.n.algoquant.util.config.AQConfig,194 - looking up configuration file: config.default.xml
... excerpt shortened; complete stdout is in the release archive ...
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at dev.nm.misc.parallel.ParallelExecutor.executeAll(bwb:217)
	at dev.nm.misc.parallel.ParallelExecutor.forEach(bwb:323)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.s(eh:153)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.preComputeBaskets(eh:96)
	at tech.nmfin.algoquant.demo.model.daspremont2008.MultiPeriodKagiMRStrategyDemo.main(MultiPeriodKagiMRStrategyDemo.java:67)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at ModelDemoRunner.main(ModelDemoRunner.java:35)
Caused by: java.lang.IllegalArgumentException: List length = -1
	at java.util.Collections.nCopies(Collections.java:4986)
	at dev.nm.algebra.linear.matrix.doubles.operation.MatrixUtils.deColumnMean(pfc:101)
	at dev.nm.stat.descriptive.covariance.SampleCovariance.b(jlb:30)
	at dev.nm.stat.descriptive.covariance.SampleCovariance.<init>(jlb:168)
	at dev.nm.stat.descriptive.covariance.SampleCovariance.<init>(jlb:3)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.ClusterFinder.s(uo:204)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.ClusterFinder.findClusters(uo:130)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.ClusterFinder.findLargestCluster(uo:205)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.MRMultiBasketFinder.findBaskets(ul:28)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.SimpleMRBasketProvider.s(mf:91)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.SimpleMRBasketProvider.basketsAtTime(mf:92)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.MRBasketProviderCachedFactory.preComputeBasket(gl:72)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.s(eh:102)
	at dev.nm.misc.parallel.ParallelExecutor$2.call(bwb:385)
	at dev.nm.misc.parallel.ParallelExecutor$2.call(bwb:287)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)

java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: List length = -1
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at dev.nm.misc.parallel.ParallelExecutor.executeAll(bwb:217)
	at dev.nm.misc.parallel.ParallelExecutor.forEach(bwb:323)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.s(eh:153)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.preComputeBaskets(eh:96)
	at tech.nmfin.algoquant.demo.model.daspremont2008.MultiPeriodKagiMRStrategyDemo.main(MultiPeriodKagiMRStrategyDemo.java:67)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at ModelDemoRunner.main(ModelDemoRunner.java:35)
Caused by: java.lang.IllegalArgumentException: List length = -1
	at java.util.Collections.nCopies(Collections.java:4986)
	at dev.nm.algebra.linear.matrix.doubles.operation.MatrixUtils.deColumnMean(pfc:101)
	at dev.nm.stat.descriptive.covariance.SampleCovariance.b(jlb:30)
	at dev.nm.stat.descriptive.covariance.SampleCovariance.<init>(jlb:168)
	at dev.nm.stat.descriptive.covariance.SampleCovariance.<init>(jlb:3)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.ClusterFinder.s(uo:204)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.ClusterFinder.findClusters(uo:130)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.ClusterFinder.findLargestCluster(uo:205)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.MRMultiBasketFinder.findBaskets(ul:28)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.SimpleMRBasketProvider.s(mf:91)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.SimpleMRBasketProvider.basketsAtTime(mf:92)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.strategy.MRBasketProviderCachedFactory.preComputeBasket(gl:72)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.s(eh:102)
	at dev.nm.misc.parallel.ParallelExecutor$2.call(bwb:385)
	at dev.nm.misc.parallel.ParallelExecutor$2.call(bwb:287)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)


	at dev.nm.misc.parallel.ParallelExecutor.executeAll(bwb:95)
	at dev.nm.misc.parallel.ParallelExecutor.forEach(bwb:323)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.s(eh:153)
	at tech.nmfin.algoquant.model.meanreversion.daspremont2008.simulation.MultiPeriodKagiMRStrategySim.preComputeBaskets(eh:96)
	at tech.nmfin.algoquant.demo.model.daspremont2008.MultiPeriodKagiMRStrategyDemo.main(MultiPeriodKagiMRStrategyDemo.java:67)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at ModelDemoRunner.main(ModelDemoRunner.java:35)
09:08:28.212 [main] INFO  t.n.a.m.m.d.s.MultiPeriodKagiMRStrategySim,68 - pre-computed baskets: 

Downloadable evidence

Download MultiPeriodKagiMRStrategyDemo.zip contains stdout, stderr, the execution record, checksums and any exported CSV/chart files.

Export Bytes
files/log/SP500-constituents.csv 21718
files/log/basket.series.20261018090828/basket.series.combined.csv 0
files/log/basket.series.20261018090828/basket.series.in.sample.csv 0
files/log/basket.series.20261018090828/basket.series.out.of.sample.csv 0

Interpreting the result

Use the first relevant exception and the source configuration to resolve the prerequisite or code issue, then rerun. A missing dataset requires the correct original schema and period; substituting synthetic values would be a different experiment. A timeout establishes only that this bounded attempt did not finish.

For model assumptions, original publications and adaptation limits, use the literature guide.

Clone this wiki locally