STRASMORE/EXPLORE 2,469 QUERIES

bos_by_name

Answered against 22 years of US equities and 12 years of US options data and published with the query that produced it. This result is stored as of 2026-09-22, from market-structure-and-break-of-structure.

as of table 6×5read in context →
bos_by_name — 6 rows by 5 columns, computed from US exchange, SIP and OPRA data.
tickerbos_eventscontinuation_pctbase_rate_pctedge_pp
AAPL7064.356.77.6
SPY826162.2-1.2
MSFT7454.155.5-1.4
KO7353.455.6-2.2
QQQ7357.560-2.5
JPM8048.857.8-9
Rows × columns
6 × 5
Computed
Completeness
No missing values
Source
US exchange, SIP and OPRA market data
Licence
Strasmore terms · free, no signup
Formats
JSON · CSV · the SQL below

What each column holds

Column definitions for bos_by_name, derived from the stored result.
ColumnTypeRangeNotes
ticker text 6 distinct values (AAPL, JPM, KO…)
bos_events number 70 to 82
continuation_pct number 48.8 to 64.3 percent
base_rate_pct number 55.5 to 62.2 percent
edge_pp number -9 to 7.6

Computed from Strasmore's warehouse of US exchange, SIP and OPRA market data. Equity prices are delayed; options greeks and implied volatility are end-of-day. This result is stored, not recomputed on load — it is exactly the numbers that were returned on , and the query below is what returned them.

Run it yourself

This is the exact query behind the result above. Change a ticker, a date or a column and run it against the warehouse — no account, no key. The no-signup tier is smaller than the one this page was computed on; a query that reaches past it comes back saying which plan runs it.

WITH
px AS
(
    SELECT
        ticker,
        date,
        toFloat64(high)  AS h,
        toFloat64(close) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker IN ('AAPL', 'JPM', 'KO', 'MSFT', 'QQQ', 'SPY')
      AND date >= '2021-01-01'
      AND date <  '2026-09-01'
),
sorted AS
(
    SELECT
        ticker,
        arraySort(x -> x.1, groupArray((date, h, c))) AS bars
    FROM px
    GROUP BY ticker
),
arrs AS
(
    SELECT
        ticker,
        arrayMap(x -> x.2, bars) AS highs,
        arrayMap(x -> x.3, bars) AS closes
    FROM sorted
),
pivots AS
(
    SELECT
        ticker,
        highs,
        closes,
        arrayJoin(arrayFilter(i ->
            (i > 3)
            AND (i <= length(highs) - 3)
            AND (highs[i] > arrayMax(arraySlice(highs, i - 3, 3)))
            AND (highs[i] > arrayMax(arraySlice(highs, i + 1, 3))),
            arrayEnumerate(highs))) AS pivot_i
    FROM arrs
),
breaks AS
(
    SELECT
        ticker,
        closes,
        pivot_i,
        highs[pivot_i] AS level,
        pivot_i + 3 + arrayFirstIndex(x -> x > highs[pivot_i], arraySlice(closes, pivot_i + 4, 30)) AS break_i
    FROM pivots
    WHERE arrayFirstIndex(x -> x > highs[pivot_i], arraySlice(closes, pivot_i + 4, 30)) > 0
),
events AS
(
    SELECT
        ticker,
        break_i,
        argMax(level, pivot_i) AS level,
        any(closes)            AS closes
    FROM breaks
    GROUP BY ticker, break_i
),
by_name AS
(
    SELECT
        ticker,
        count()                                                     AS bos_events,
        round(100 * avg(closes[break_i + 10] > closes[break_i]), 1) AS continuation_pct
    FROM events
    WHERE break_i + 10 <= length(closes)
    GROUP BY ticker
),
base AS
(
    SELECT
        ticker,
        round(100 * avg(closes[t + 10] > closes[t]), 1) AS base_rate_pct
    FROM
    (
        SELECT
            ticker,
            closes,
            arrayJoin(arrayEnumerate(closes)) AS t
        FROM arrs
    )
    WHERE t + 10 <= length(closes)
    GROUP BY ticker
)
SELECT
    e.ticker                                       AS ticker,
    e.bos_events                                   AS bos_events,
    e.continuation_pct                             AS continuation_pct,
    b.base_rate_pct                                AS base_rate_pct,
    round(e.continuation_pct - b.base_rate_pct, 1) AS edge_pp
FROM by_name AS e
INNER JOIN base AS b ON b.ticker = e.ticker
ORDER BY edge_pp DESC
⌘/Ctrl + Enter