# Generated by tools/build_contracts.py from tools/algoseek_catalog.py -- do not edit by hand.
# Open Data Contract Standard v3.2.0 (https://bitol-io.github.io/open-data-contract-standard/).
apiVersion: v3.2.0
kind: DataContract
id: urn:alphaswarm:datacontract:algoseek:us-equities-otc-quote
name: AlgoSeek US Equities OTC Quote
version: 0.1.0
status: draft
domain: market-data
tags:
- algoseek
- licensed-data
- equity
- us
- tick
description:
  purpose: One row is one quote record from the OTC Link inter-dealer quotation system (individual market-participant
    quote events plus derived inside-market quotes), as compiled in OTC Markets Group's end-of-day Quote
    History file. Used to study quoting activity in OTC securities.
  usage: Backtesting, execution and microstructure research, feature engineering for US equities.
  limitations: 'Delivered as recorded from the source feed: AlgoSeek does not remove crossed or locked
    quotes, bad prints, or out-of-sequence packets unless contracted to. Consumers own cleaning. Sample
    channel: S3 CSV (sample_channel s3/cloud_storage, eq_otc_taq.csv, 100 rows, GBRRF on 2024-01-25);
    no ArdaDB table sample. The JSON preview is identical to the CSV. Mixed record kinds in one table:
    QuoteUpdateType 6 rows are derived OTC Link inside-market quotes (MMID and Trader blank, InsideReason
    set); types 1-5 are individual participant quote events. Filter by type before aggregating sizes to
    avoid double counting. Blank semantics per guide: MMID, Trader and InsideReason are Blank (empty)
    where not applicable (MMID/Trader empty on type 6; InsideReason empty on types 1-5); all other fields
    are ''Never'' missing. Unpriced sides use Type U with Price 0 and Size 0 (not empty). In the sample
    all 34 type-6 rows immediately follow an individual-quote row with the same Timestamp and a QuoteId
    3 higher; not every individual update produces an inside row (only when the inside changes), and an
    inside size can aggregate several participants (e.g. AskSize 2000 vs 1000).'
  authoritativeDefinitions:
  - type: businessDefinition
    url: https://algoseek.com/dataset/us-equities-otc-quote/
  - type: implementation
    url: https://algoseek.com/data-docs/equity-market-data/algoseek.US.Equity.OTC.Quote.pdf
  - type: implementation
    url: https://algoseek.com/docs/rest-api/reference
context:
  instructions: Times are local US Eastern clock times (DST-aware), not UTC. Treat TRADE NB / NBBO-flagged
    rows as the backtest-grade subset. Cancellations reference earlier trades and can arrive hours later,
    so aggregate only after the session closes. Prices are unadjusted unless the dataset name says Adjusted;
    join us-equities-*-adjustment-factors on SecId for adjustment.
  verifiedStatements:
  - id: vs1
    question: What time zone are the timestamps in?
    answer: US Eastern local time with daylight saving (the guides label it EST/ET).
  - id: vs2
    question: Are prices adjusted for splits and dividends?
    answer: Only in datasets whose name contains Adjusted; all others are as traded.
  constraints:
  - id: c1
    constraint: 'Licensed vendor data: never export raw rows to a tenant-local destination or include
      them verbatim in a public artifact; serve only through entitlement-checked platform reads.'
  - id: c3
    constraint: Do not treat the vendor's `Ticker` as a stable identity across time; join on an AlgoSeek
      security key (SecId or ASID, which are distinct) or the platform symbol mapping.
servers:
- server: algoseek-s3
  type: s3
  environment: vendor
  description: AlgoSeek flat-file delivery (the layout the schema below describes).
  location: s3://${ALGOSEEK_S3_BUCKET_EQ_OTC_TAQ}/
  format: csv
  encoding: UTF-8
  customProperties:
  - property: layout
    value: Plain-text CSV with a fixed header row; by default one file per symbol per trading day (e.g.
      all AAALY events on 2023-10-25 in one file); gzip-compressed (.csv.gz, ~8:1). Source is the OTC
      Markets Group SFTP server; no bucket/key path is documented.
  - property: compression
    value: gzip
  - property: header
    value: true
  - property: entitlement
    value: Bucket access is granted per subscription; bucket names arrive with license provisioning.
- server: algoseek-rest-api
  type: api
  environment: vendor
  description: AlgoSeek Datasets REST API (X-API-KEY header; JSON, CSV or gzipped CSV). Returns AlgoSeek's
    normalized API layout, which differs from the flat-file columns in this contract's schema.
  location: https://api.algoseek.com/v1/data/us-equity/otc-taq/:trade_date/:identifier
  customProperties:
  - property: auth
    value: X-API-KEY header issued by AlgoSeek
  - property: columnsEndpoint
    value: https://api.algoseek.com/v1/meta/datasets/{dataset_id}/columns
  - property: statusEndpoint
    value: https://api.algoseek.com/v1/meta/datasets/{dataset_id}/status
  - property: responseFormats
    value:
    - json
    - csv
    - csv_gzip
  - property: pagination
    value: offset + limit; tick endpoints take trade_date and identifier (Ticker or ASID) in the path
schema:
- name: us_equities_otc_quote
  physicalName: eq_otc_taq
  physicalType: file
  logicalType: object
  businessName: US Equities OTC Quote
  description: One row is one quote record from the OTC Link inter-dealer quotation system (individual
    market-participant quote events plus derived inside-market quotes), as compiled in OTC Markets Group's
    end-of-day Quote History file. Used to study quoting activity in OTC securities.
  dataGranularityDescription: one quote event (add/update/delete/start-of-day/open-close) by one market
    participant, or one derived inside-market quote, for one OTC ticker on one trading date
  properties:
  - name: TradeDate
    logicalType: date
    logicalTypeOptions:
      format: yyyymmdd
    physicalType: string (yyyymmdd) (csv text)
    description: Trading date of the quote record.
    primaryKey: true
    primaryKeyPosition: 1
    required: true
    partitioned: true
    partitionKeyPosition: 1
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: Timestamp
    logicalType: time
    logicalTypeOptions:
      format: HH:MM:SS.mmm
    physicalType: string (HH:MM:SS.mmm) (csv text)
    description: Quote time of day to the millisecond; zone not stated in the field table (guide's trading-hours
      section uses ET).
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: QuoteUpdateType
    logicalType: integer
    logicalTypeOptions:
      format: i64
    physicalType: integer (csv text)
    description: 'Record type of the quote: update, add, delete, start-of-day, open/close update, or inside-market
      quote.'
    required: true
    enum:
    - value: '1'
      label: Update
    - value: '2'
      label: Add
    - value: '3'
      label: Delete
    - value: '4'
      label: Start of Day (quote generated at system start; closed the previous day but not withdrawn/deleted)
    - value: '5'
      label: Open/Close Update (caused by a trader open/close status change)
    - value: '6'
      label: Inside (OTC Link inside-market quote derived from the individual quotes)
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: Ticker
    logicalType: string
    physicalType: string (csv text)
    description: Security symbol.
    primaryKey: true
    primaryKeyPosition: 2
    required: true
    partitioned: true
    partitionKeyPosition: 2
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: Name
    logicalType: string
    physicalType: string (csv text)
    description: Security name.
    required: true
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: BidType
    logicalType: string
    physicalType: string (csv text)
    description: 'Kind of bid: priced, unpriced, or offer wanted.'
    enum:
    - value: A
      label: Actual (priced)
    - value: U
      label: Unpriced
    - value: OW
      label: Offer Wanted
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: BidPrice
    logicalType: number
    physicalType: decimal (csv text)
    description: 'Bid price: 4 decimals under $1, 2 above; minimum $0.0001, maximum $999,999.99; 0 when
      the bid is unpriced.'
    required: true
    customProperties:
    - property: unit
      value: USD
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: BidSize
    logicalType: integer
    logicalTypeOptions:
      format: i64
    physicalType: integer (csv text)
    description: Bid size in shares, at most 999,999,999; 0 when unpriced.
    required: true
    customProperties:
    - property: unit
      value: shares
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: AskType
    logicalType: string
    physicalType: string (csv text)
    description: 'Kind of ask: priced, unpriced, or bid wanted.'
    enum:
    - value: A
      label: Actual (priced)
    - value: U
      label: Unpriced
    - value: BW
      label: Bid Wanted
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: AskPrice
    logicalType: number
    physicalType: decimal (csv text)
    description: 'Ask price: 4 decimals under $1, 2 above; minimum $0.0001, maximum $999,999.99; 0 when
      the ask is unpriced.'
    required: true
    customProperties:
    - property: unit
      value: USD
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: AskSize
    logicalType: integer
    logicalTypeOptions:
      format: i64
    physicalType: integer (csv text)
    description: Ask size in shares, at most 999,999,999; 0 when unpriced.
    required: true
    customProperties:
    - property: unit
      value: shares
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: UnsolicitedFlag
    logicalType: string
    logicalTypeOptions:
      format: 0/1 flag
    physicalType: string (csv text)
    description: 1 marks an unsolicited quote; the sample only ever shows 0.
    enum:
    - value: '1'
      label: Unsolicited flag true
    - value: '0'
      label: not flagged (sample only; the guide documents just '1')
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: MMID
    logicalType: string
    physicalType: string (csv text)
    description: Market participant that submitted the quote; blank on inside quotes (QuoteUpdateType
      6).
    customProperties:
    - property: nullMeaning
      value: Blank
    - property: evidence
      value: guide+sample
  - name: Trader
    logicalType: string
    physicalType: string (csv text)
    description: Trader id of the submitting trader; blank on inside quotes (QuoteUpdateType 6).
    customProperties:
    - property: nullMeaning
      value: Blank
    - property: evidence
      value: guide+sample
  - name: OpenCloseStatus
    logicalType: integer
    logicalTypeOptions:
      format: i64
    physicalType: integer (csv text)
    description: Whether the quote is open (1) or closed (0); only open quotes feed the inside market.
    required: true
    enum:
    - value: '0'
      label: Closed
    - value: '1'
      label: Open (only open quotes can be considered for the inside)
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: QuoteId
    logicalType: integer
    logicalTypeOptions:
      format: i64
    physicalType: integer (csv text)
    description: Unique quote identification number; every one of the 100 sample rows has a different
      value.
    primaryKey: true
    primaryKeyPosition: 3
    required: true
    customProperties:
    - property: nullMeaning
      value: Never
    - property: evidence
      value: guide+sample
  - name: InsideReason
    logicalType: string
    physicalType: string (csv text)
    description: Why the inside market changed; populated only when QuoteUpdateType is 6, otherwise blank.
    enum:
    - value: Quote Updated
      label: inside changed by a quote update
    - value: Quote Added
      label: inside changed by a new quote
    - value: Quote Deleted
      label: inside changed by a quote deletion
    - value: Trader Open Quote
      label: inside changed because a trader opened a quote
    - value: Trader Close Quote
      label: inside changed because a trader closed a quote
    customProperties:
    - property: nullMeaning
      value: Blank
    - property: evidence
      value: guide+sample
  quality:
  - id: row_count_positive
    metric: rowCount
    mustBeGreaterThan: 0
    dimension: completeness
    severity: error
    description: Every delivered partition (trade date, or snapshot) carries at least one row.
  - id: primary_key_unique
    metric: duplicateValues
    mustBe: 0
    arguments:
      properties:
      - TradeDate
      - Ticker
      - QuoteId
    dimension: uniqueness
    severity: warning
    description: 'Best-effort key for an event stream: same-timestamp events from one venue can repeat,
      so duplicates are reported, not rejected.'
  - id: AskSize_non_negative
    type: sql
    description: AskSize is never negative.
    query: SELECT COUNT(*) FROM {object} WHERE AskSize < 0
    mustBe: 0
    dimension: accuracy
    severity: error
  - id: BidSize_non_negative
    type: sql
    description: BidSize is never negative.
    query: SELECT COUNT(*) FROM {object} WHERE BidSize < 0
    mustBe: 0
    dimension: accuracy
    severity: error
support:
- channel: algoseek-support
  tool: email
  url: mailto:support@algoseek.com
  scope: issues
  description: Vendor support for data defects, missing days, and entitlement problems.
team:
  name: AlphaSwarm data engineering
slaProperties:
- id: update_frequency
  property: frequency
  value: 1
  unit: d
  driver: analytics
- id: retention
  property: retention
  value: license-term
  description: Retention of landed copies is bounded by the AlgoSeek license; purge on termination.
  driver: regulatory
customProperties:
- property: vendor
  value: AlgoSeek
- property: vendorDataGroup
  value: us-equity
- property: vendorDatasetTextId
  value: eq_otc_taq
- property: vendorSampleUrl
  value: https://as-metadata-services-assets.s3.amazonaws.com/sample_data/cloud_storage/eq_otc_taq.csv
- property: assetClass
  value: equity
- property: venues
  value:
  - OTC Link (OTC Markets Group inter-dealer quotation system)
- property: coverage
  value: All quotes submitted to the OTC Link inter-dealer quotation system and distributed in OTC Markets
    Group's OTC Quote History file; inside quotes cover quotes entered in OTC Link only (other inter-dealer
    systems are excluded). History start is not stated.
- property: timezone
  value: America/New_York
- property: timestampFormat
  value: HH:MM:SS.mmm (millisecond)
- property: sessionHours
  value: OTC Markets normal hours Mon-Fri 09:30-16:00 ET; OTC Link ATS operating hours Mon-Fri 06:00-17:00
    ET; start-of-day records in the sample are stamped 00:50:04.760
- property: priceAdjustment
  value: unadjusted
- property: licensedData
  value: true
- property: evidenceGrade
  value: vendor-doc
- property: knownIssues
  value:
  - Primary key is inferred; AlgoSeek's guide does not name one.
  - 'Doc discrepancy: UnsolicitedFlag: guide documents only ''1 = Unsolicited Flag True''; every sample
    row is ''0'' (an undocumented value, presumably false).'
  - 'Doc discrepancy: BidType/AskType: guide lists A, U and OW (bid) / BW (ask); the sample only shows
    A and U.'
  - 'Doc discrepancy: Timestamp: the field table gives no time zone; only the trading-hours section mentions
    ET. Sample start-of-day records are stamped 00:50:04.760, outside the stated OTC Link hours (06:00-17:00
    ET).'
  - 'Doc discrepancy: QuoteId is described as ''unique'' without a scope; in the sample it is unique per
    row and rises with time, and each update of the same participant''s quote (e.g. MCAP) carries a new
    QuoteId, so it behaves like a record sequence number rather than a stable id for one quote across
    its updates.'
  - 'Doc discrepancy: Price precision text (4 decimals under $1, 2 above) is a maximum; sample prices
    such as 0.742, 0.43 and 0.0001 show 1-4 decimals and unpriced sides are 0.'
  - 'Doc discrepancy: No history start date is given in the guide or on the page; the guide cites 2023-10-25
    as an example date and the sample is 2024-01-25.'
contractCreatedTs: '2026-11-02T00:00:00Z'
