334 n_trials: int |
None =
None,
335 max_work: int |
None =
None,
337 """Return one selected trial's DSR document, or raise ``DsrError``.
339 N defaults to all rows read; a caller may only increase it. ``max_work`` bounds
340 rows read + eligible rows before exact arithmetic is performed.
342 _check_parameters(series, selected, n_trials, max_work)
344 loaded = read_source(source)
345 check_context(loaded.rows)
346 except RowsError
as error:
347 ids = [item[1]
if isinstance(item, tuple)
else item
for item
in error.ids]
349 "rows_incomplete":
"dsr_rows_incomplete",
350 "context_mismatch":
"dsr_context_mismatch",
351 }.get(error.kind,
"dsr_input_invalid")
352 raise DsrError(code, error.detail, ids, error.names)
from None
353 rows = sorted(loaded.rows, key=
lambda row: row.trial_id)
354 names = tuple(f
"returns.{series}.{field}" for field
in _FIELDS)
356 invalid_names = set()
359 if row.metrics
is None or name
not in row.metrics:
361 value = row.metrics[name]
364 except (TypeError, ValueError, OverflowError, RecursionError):
366 if type(value)
is int
and name != names[-1]:
368 invalid_ids.add(row.trial_id)
369 invalid_names.add(name)
373 "a series entry cannot be written as JSON",
375 sorted(invalid_names),
382 if row.status !=
"ok":
383 reason = f
"status_{row.status}"
384 elif row.metrics
is None or any(name
not in row.metrics
for name
in names):
385 reason =
"returns_not_recorded"
387 sr, count, skew, kurt, status = (row.metrics[name]
for name
in names)
388 if type(status)
is not int
or status != 0:
389 reason =
"returns_status_nonzero"
390 status_values.append(status)
392 sr, skew, kurt = _number(sr), _number(skew), _number(kurt)
397 or type(count)
is not int
398 or not 2 <= count <= 1 << 53
400 reason =
"returns_unavailable"
402 eligible[row.trial_id] = (sr, count, skew, kurt)
403 if reason
is not None:
404 reasons.setdefault(reason, []).append(row.trial_id)
406 raise DsrError(
"dsr_no_eligible_rows",
"no row remains after exclusions")
407 if len(eligible) == 1:
409 "dsr_too_few_eligible_rows",
410 "only one eligible row remains",
413 if selected
not in {row.trial_id
for row
in rows}:
415 "dsr_selected_unknown",
"selected trial was not read", (selected,)
417 if selected
not in eligible:
418 reason = next(reason
for reason, ids
in reasons.items()
if selected
in ids)
420 "dsr_selected_not_eligible",
421 "selected trial is excluded",
425 rows_read = len(rows)
426 if n_trials
is not None and n_trials < rows_read:
428 "dsr_trials_inconsistent",
429 "n_trials is below the number of rows read",
432 work = rows_read + len(eligible)
433 if max_work
is not None and work > max_work:
435 "dsr_resource_exceeded",
436 f
"admission figure {work} is above max_work {max_work}",
438 n = rows_read
if n_trials
is None else n_trials
439 values = {identifier: stats[0]
for identifier, stats
in eligible.items()}
440 v, sr0, den, z, result = _statistic(values, eligible[selected], n, selected)
441 sr, count, skew, kurt = eligible[selected]
443 for reason
in sorted(reasons):
444 entry = {
"count": len(reasons[reason]),
"ids": reasons[reason]}
445 if reason ==
"returns_status_nonzero":
446 entry[
"statuses"] = _statuses(status_values)
447 excluded[reason] = entry
449 "contract": CONTRACT,
452 "selected": selected,
453 "sharpe_per_period": sr,
458 "n_trials_source":
"rows_read" if n_trials
is None else "caller",
459 "variance_basis":
"sample_n_minus_1",
465 "selected_is_max": sr == max(values.values()),
466 "rows_read": rows_read,
467 "rows_eligible": len(eligible),
468 "rows_excluded": rows_read - len(eligible),
469 "eligible": list(eligible),
470 "excluded": excluded,
471 "algorithm": ALGORITHM,
472 "input_sha256": _input_digest(rows, names),
473 "interpretation": INTERPRETATION,