Interface BacktestOutcome
- All Known Implementing Classes:
BacktestOutcome.Aborted,BacktestOutcome.Completed,BacktestOutcome.Failed,BacktestOutcome.InProgress
QTSurfer.backtestResult(String, String) for a job the calling
process did not necessarily start.
Four answers, and they are not invented here: they are the four cases the SDK's own poll loop already reasons in when it decides whether a run is still moving. Reading a run without running it has to keep them apart, so they are the variants of this type:
BacktestOutcome.Completed— the run finished and its numbers are final.BacktestOutcome.Failed— the run finished badly. A real answer, not an error.BacktestOutcome.Aborted— the run was cancelled. Also a real answer.BacktestOutcome.InProgress— the platform knows the job but has nothing final to report yet.
Why a sealed type rather than the results alone. The
workflow path — Backtest.await() and the backtest(...)
shortcut — hands back a bare ResultMap because it reports the two
bad endings out of band, completing exceptionally with
QTSExecutionError or
QTSCanceledError. A standalone read
cannot borrow that channel: asking "what happened to this job?" and being
told "it failed" is the question being answered, not the read going wrong.
With the exception channel gone, the status has to travel in the return
value or it does not travel at all — and the platform always sends it, so
dropping it would be discarding the answer.
Matching on the variants is the intended use:
BacktestOutcome outcome = qts.backtestResult("binance", jobId);
if (outcome instanceof BacktestOutcome.Completed c) {
report(c.results().getPnlTotal());
} else if (outcome instanceof BacktestOutcome.Failed f) {
report("failed: " + f.state().getStatusDetail());
} else if (outcome instanceof BacktestOutcome.Aborted) {
report("cancelled");
} else {
report("still running; ask again later");
}
This library targets Java 17, where a switch over the variants is
still a preview feature — hence the instanceof chain. On a newer
runtime the sealing makes that switch exhaustive without a default.
A job id the platform does not recognise is not one of these. That is the
one answer that stays an exception — see
QTSurfer.backtestResult(String, String).
The links above point at QTSurfer for concreteness;
AuthenticatedClient carries the same
method with the same semantics, and this type is what both return.
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic final recordThe run was cancelled.static final recordThe run finished and produced its numbers.static final recordThe run finished badly.static final recordThe platform knows this job but has nothing final to report yet. -
Method Summary
Modifier and TypeMethodDescriptionbooleanfinished()Whether the run has stopped moving.com.qtsurfer.api.client.model.ResultMapresults()The run's numbers, exactly as the platform sent them.com.qtsurfer.api.client.model.JobStatestate()The platform's job record, carrying the raw status, the progress counts, and — on a run that ended badly —JobState.getStatusDetail().
-
Method Details
-
state
com.qtsurfer.api.client.model.JobState state()The platform's job record, carrying the raw status, the progress counts, and — on a run that ended badly —JobState.getStatusDetail().Non-
nullon every terminal variant — a run cannot be reported as finished, failed or cancelled without the platform having said so.BacktestOutcome.InProgressis the only variant where it may be absent, and it is absent for one reason: the platform answered without a body, which is how it reports a job it knows but cannot yet describe. AnBacktestOutcome.InProgressthat came from an unrecognised or missing status on a response that did carry a body has one. Either way, read it defensively on that variant.- Returns:
- the job record; may be
nullonBacktestOutcome.InProgress
-
results
com.qtsurfer.api.client.model.ResultMap results()The run's numbers, exactly as the platform sent them.Only final on
BacktestOutcome.Completed. The field is carried on every variant rather than dropped, because the platform always sends it and this SDK is not the right place to decide it is uninteresting — but a run that has not finished, or that ended badly, has at best a partial account of itself here, and it can be absent entirely.- Returns:
- the result map, or
nullwhen the response carried none
-
finished
boolean finished()Whether the run has stopped moving.trueforBacktestOutcome.Completed,BacktestOutcome.FailedandBacktestOutcome.Abortedalike — finishing badly is still finishing, and re-reading will not change the answer.- Returns:
trueunless this isBacktestOutcome.InProgress
-