---
name: asx-short-report
description: >-
  Query daily ASIC short-selling data for the Australian share market (ASX):
  fetch the latest or historical processed reports, ranked short-interest
  anomalies, structured per-stock risk assessments, AI market narratives, and
  the list of archived report dates. Use when the user asks about ASX short
  positions, short interest, short-selling, squeeze risk, or the
  asic-short-position-processor API.
---

# ASX Short Position Report

A Cloudflare Worker that turns the official (public) ASIC short-selling
registry into a structured, enriched feed for the Australian market. Data
carries a T+4 reporting lag relative to the trading day.

- Base URL: `https://asic-short-position-processor.flare-oracle.workers.dev`
- Discovery doc: `/llms.txt` (also at `/llms-full.txt`)
- OpenAPI contract: `/api/v1/openapi.json`

## How to use

Call the REST endpoints directly with plain HTTP GET.

### REST API

| Method | Route | Returns |
|--------|-------|---------|
| GET | `/api/v1/asic/latest` | Full latest report JSON |
| GET | `/api/v1/asic/latest/narrative` | Latest narrative, plain text |
| GET | `/api/v1/asic/latest/assessment` | `{ asic_reporting_date, assessment }` |
| GET | `/api/v1/asic/dates` | `{ count, dates[] }` newest first (free) |
| GET | `/api/v1/asic/report/{date}` | Archived full report |
| GET | `/api/v1/asic/report/{date}/narrative` | Archived narrative |
| GET | `/api/v1/asic/report/{date}/assessment` | Archived assessment |
| GET | `/api/v1/asic/squeeze-candidates?min_cover=3&confirmed=false&limit=20` | Ranked squeeze candidates (days_to_cover filter, borrow_pressure sort; `catalyst=true` for CATALYST_PRESENT only; `holder=true` for HOLDER_NOTICE only; `signal=squeeze_watch&min_conviction=30` for Story 3 composite-signal rows) |
| GET | `/api/v1/asic/status` | Freshness + next scheduled run (free) |
| GET | `/api/v1/asic/trigger` | POST, guarded by TRIGGER_SECRET, runs pipeline |

## Data model

- `market_data[]`: `asx_code`, `company_name`, `short_shares`,
  `total_issued_shares`, `short_interest_pct`.
- `anomaly_matrix[]`: `asx_code`, `short_interest_pct`, `prior_day_pct`,
  `delta_pct`, `consecutive_rising_days`, `anomaly_type`
  (`HIGH_SHORT_SQUEEZE_RISK | RAPID_ACCUMULATION | SUSTAINED_ACCUMULATION |
  HARD_TO_BORROW | VOLUME_CONFIRMED | SHORTS_UP_PRICE_HOLDING |
  CATALYST_PRESENT | RESULTS_WEEK | CAP_RAISE_OVERHANG | HOLDER_NOTICE |
  HOLDER_CUSTODIAL`),
  `risk_score` (0-100), `history_percentile_60d`, `sector`, `industry`,
  `market_cap`, `price_aud`, `squeeze_probability`, plus Story 1 price/volume
  join: `price_close`, `volume_today`, `avg_vol_20d`, `days_to_cover`,
  `volume_spike_ratio`, `divergence_flag`, `borrow_pressure`, `price_as_of`,
  `price_stale`, plus Story 2 catalyst join: `catalyst_count_3d` (0 = no
  announcements in window, never null), `catalyst_headlines` (top 3),
  `results_week`, `cap_raise_overhang`, plus Story 4 holder join:
  `holder_count_3d` (subset of catalyst count, independent of priceSensitive),
  `holder_headlines` (top 3, metadata only — direction unknown, never infer
  buy/sell), `holder_present`, `holder_custodial` (notice names a known
  agent-lender/prime broker — borrowed/client stock possible), plus Story 6
  parsed direction: `holder_nature`
  (beneficial|borrowed|custodial|mixed|unknown, null when no parse —
  overrides the headline heuristic), `borrowed_pct`, `offsetting_short_pct`
  (first observed short number), flags `BORROWED_HOLDING` (borrowed stock
  overhang — scoring caps at accumulation_watch/60, read as borrow-supply)
  and `HOLDER_RETURN` (borrower returning stock = covering flow),
  plus Story 3 composite signal:
  `price_5d_pct`, `signal`
  (`squeeze_watch|accumulation_watch|event_driven_watch|quiet`,
  positioning-heavy 40/30/15/15, >=2 pillars), `signal_conviction` (0-100),
  `signal_confidence` (high|medium|low), `signal_drivers` (cite only these).
  Signals are watch labels, never buy/sell advice.
- `risk_assessment[]`: `asx_code`, `severity` (`LOW|MEDIUM|HIGH`),
  `direction` (`accumulating|declining|stable`), `status` (`new|continuing`),
  `summary` (<=20 words).
- Clean days return an empty `risk_assessment` and the narrative "No anomalies
  flagged today."

## Gotchas

- Report dates are ASIC reporting dates (`YYYY-MM-DD`, T+4 lag), not calendar
  days. Use `list_available_dates` / `GET /api/v1/asic/dates` to discover which
  dates exist; a date with no archived report returns 404.
- Paid REST routes settle via x402 (USDC on Base) once the Monetization Gateway
  is live; discovery and documentation routes are free and always available.
- Price/volume fields are null with `price_stale: true` when the Yahoo join
  missed that run — the deterministic risk numbers are unaffected.
- `catalyst_count_3d: 0` means no ASX announcements within ±3d of the report
  date (valid data, not a miss). Headlines are metadata only; no PDF parsing.
- `price_as_of` may differ from `asic_reporting_date`: shorts carry a T+4 lag
  while joined prices and announcements are T+0; never present them as simultaneous.
- The `trigger` endpoint requires `Authorization: Bearer <TRIGGER_SECRET>`.
