Explore more topics
Market-data lake

lake.backtest_runs dataset schema

Column types and research semantics for NexusTrade’s lake.backtest_runs dataset. Read the supported schema before submitting a bounded SQL query.

Jump to a section

TL;DR

Use lake.backtest_runs for run statistics, but deduplicate on experiment_id before ranking or averaging performance. Exclude optimizer attempts when asking which retained strategies performed well, and compare similar assets, cadences and date windows. Keep backtest_uuid to retrieve the full rules. Baseline and alpha fields are unevenly populated, so restrict comparisons to eligible nonnull records. This page supplies an unexecuted query example and logical schema, not a finding that any strategy wins.

Query name
lake.backtest_runs
Storage partition
snapshot
Columns
51

Columns and types

VARCHAR

  • backtest_uuid
  • portfolio_uuid
  • experiment_id
  • author_type
  • date_range_bucket
  • interval
  • cadence
  • asset_class

DATE

  • start_date
  • end_date

INTEGER

  • duration_days

BOOLEAN

  • has_options

Showing 12 of 51 recorded rows. The complete table is below.

Current logical schema for lake.backtest_runs

Inspect the complete lake.backtest_runs schema

Scroll sideways to compare all columns. Select a heading to sort.

backtest_uuidVARCHAR
portfolio_uuidVARCHAR
experiment_idVARCHAR
author_typeVARCHAR
start_dateDATE
end_dateDATE
duration_daysINTEGER
date_range_bucketVARCHAR
intervalVARCHAR
cadenceVARCHAR
asset_classVARCHAR
has_optionsBOOLEAN
memory_classVARCHAR
baseline_symbolVARCHAR
starting_cashDOUBLE
stock_fee_amountDOUBLE
stock_fee_typeVARCHAR
crypto_fee_amountDOUBLE
crypto_fee_typeVARCHAR
tickersVARCHAR[]
n_strategiesINTEGER
n_comparisonsINTEGER
n_indicator_instancesINTEGER
distinct_indicator_typesVARCHAR[]
distinct_action_typesVARCHAR[]
uses_temporal_gatingBOOLEAN
min_temporal_threshold_daysDOUBLE
signal_frequency_classVARCHAR
tradedBOOLEAN
warningsVARCHAR[]
percent_changeDOUBLE
sharpe_ratioDOUBLE
sortino_ratioDOUBLE
max_drawdownDOUBLE
avg_drawdownDOUBLE
ulcer_indexDOUBLE
ulcer_performance_indexDOUBLE
win_rateDOUBLE
profit_factorDOUBLE
avg_trade_pnlDOUBLE
dollars_soldDOUBLE
total_dividendsDOUBLE
total_feesDOUBLE
risk_free_rateDOUBLE
baseline_percent_changeDOUBLE
baseline_sharpe_ratioDOUBLE
baseline_max_drawdownDOUBLE
alpha_pctDOUBLE
alpha_sharpeDOUBLE
time_elapsed_msBIGINT
created_atTIMESTAMP

Current logical schema for lake.backtest_runs

Query lake.backtest_runs using the column names and types below. The query validator and engine use this logical catalog; a field absent from an older shard returns typed NULL.

What this table contains

`backtest_uuid` identifies a run. Select it whenever strategy examples are wanted: NexusTrade hydrates the full strategy JSON from `lake.backtest_strategies` by that id. `portfolio_uuid` is a stable anonymized portfolio hash.

Summarize deduplicated non-optimizer runs

Query example, not executed here. The dates and filters define the proposed research scope; returned rows and current coverage must be checked in your workspace.

Each count is distinct experiment membership after one run is retained per experiment_id. Cohorts preserve asset class, cadence, interval and date-range bucket. Inspect the experiment count and date scope before interpreting a median; this query does not claim a winning strategy.

SQL
WITH eligible_runs AS (
  SELECT *
  FROM lake.backtest_runs
  WHERE author_type <> 'optimizer'
  QUALIFY ROW_NUMBER() OVER (
    PARTITION BY experiment_id
    ORDER BY created_at DESC, backtest_uuid
  ) = 1
)
SELECT asset_class, cadence, interval, date_range_bucket,
       COUNT(*) AS experiments, MEDIAN(percent_change) AS median_return,
       MEDIAN(max_drawdown) AS median_max_drawdown
FROM eligible_runs
GROUP BY asset_class, cadence, interval, date_range_bucket
ORDER BY experiments DESC
LIMIT 20;

Submit the backtest_runs example and read back its parts

Run the exact SQL through the Python SDK

Save this page's SQL as query.sql and the runner below as query.py. Use a registered key with lake scope from Developers. The runner submits the displayed backtest_runs query once, saves its operation, waits on that same ID, saves the returned manifest and downloads its Parquet parts.

This submission has not been executed for the reference page. Inspect the SQL, dates and resource limits before running it. Reuse the request key only for this identical SQL and limits; use a new key when changing them.

Shell
python3 -m pip install nexustrade==1.42.0
export NEXUSTRADE_API_KEY="YOUR_LAKE_SCOPED_KEY"
python3 query.py

Python
import json
from pathlib import Path
from nexustrade import NexusTradeClient

# Save the SQL displayed on this page as query.sql.
sql = Path("query.sql").read_text()
client = NexusTradeClient.from_environment()
operation = client.create_lake_query(
    {"query": sql, "limits": {"timeoutSeconds": 30, "maxRows": 50,
                              "maxResultBytes": 1048576}},
    idempotency_key="reference-backtest_runs-20261012-v1",
)
Path("query-operation.json").write_text(json.dumps(operation, indent=2))
finished = client.wait_for_lake_query(operation["id"])
if finished["status"] != "completed":
    raise RuntimeError(finished)
manifest = client.get_lake_query_manifest(operation["id"])["result"]
Path("query-manifest.json").write_text(json.dumps(manifest, indent=2))
print(json.dumps(manifest, indent=2))
for part in manifest["parts"]:
    Path(f"query-{part['part']}.parquet").write_bytes(
        client.download_lake_query_part(operation["id"], part["part"], max_bytes=1048576)
    )

Coverage and timing

Inspect source coverage and timing before using the rows

Anonymized backtest corpus: one row per run; other backtest_* tables join on backtest_uuid.

`backtest_uuid` identifies a run. Select it whenever strategy examples are wanted: NexusTrade hydrates the full strategy JSON from `lake.backtest_strategies` by that id. `portfolio_uuid` is a stable anonymized portfolio hash.

DEDUPLICATE ON `experiment_id` before any average, median or ranking. It hashes the strategy logic plus tickers plus window, and cloned or forked portfolios repeat one experiment under many `backtest_uuid`s (about 60% of rows are repeats), so an aggregate over raw rows measures what got cloned rather than what performed. Counting rows is fine. It is a hash: never pattern-match it.

`author_type` is 'optimizer' for genetic-search output and 'unknown' otherwise. Filter `author_type <> 'optimizer'` for any question about what performs well: a genetic search is a population of attempts, not strategies anyone chose to keep, and it is about a third of the corpus.

`tickers`, `distinct_indicator_types`, `distinct_action_types` and `warnings` are VARCHAR[]. Filter by overlap, e.g. `array_length(list_intersect(tickers, ['NVDA']::VARCHAR[])) > 0`.

`asset_class` is equity, crypto, options or mixed. `cadence` is daily or intraday. `signal_frequency_class` is unconstrained, sub_daily, daily, weekly, monthly or quarterly.

`alpha_pct` and the `baseline_*` columns are populated only for runs that carried validation statistics (nearly all options runs, very few daily-equity runs). Restrict to non-null rows before comparing them across asset classes. Return per day is `percent_change / duration_days`.

Discussion

Sign in or create a free account to join the discussion.

No comments yet.