# Regulatory Short Position Change Layer (`highbrow_qualification_z7w/regulatory-short-position-change-layer`) Actor

Monitor officially disclosed net short positions across selected regulators. Get versioned change events, source-health checks, and audit-ready snapshots for risk, compliance, data, and operations workflows. Not investment advice.

- **URL**: https://apify.com/highbrow\_qualification\_z7w/regulatory-short-position-change-layer.md
- **Developed by:** [Roman Bublyk](https://apify.com/highbrow_qualification_z7w) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.01 / actor start

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Regulatory Short Position Change Layer

An adapter-based regulatory data layer for publicly disclosed net short positions. It gives capital-markets data, risk, compliance and operations teams an auditable incremental feed from official sources — **not investment advice or a trading signal**.

### What problem it solves

Regulators publish disclosures in different formats, with different disclosure thresholds, publication delays, and lifecycle rules. Downloading a file repeatedly tells a user what exists now, but not what materially changed.

This Actor maintains a per-task snapshot and emits structured events:

- `NEW_POSITION` — a newly disclosed position after the baseline run
- `POSITION_INCREASED` / `POSITION_DECREASED`
- `POSITION_CLOSED` — previously public, now absent from the current source snapshot
- `SOURCE_CORRECTION` — source metadata changed without a percentage change
- `BASELINE_POSITION` — present on the first run; deliberately not described as “new”

It also produces an integration contract around those events:

- `position-change-event` — versioned, de-duplication-friendly events with a monotonic `eventId`, `eventFingerprint`, `snapshotId`, `sourceAsOfDate`, provenance and previous/current values;
- `source-health` — one record per selected source with retrieval status, counts, source fingerprint and explicit errors;
- `run-summary` — operational totals and a transparent initial-baseline flag;
- `LATEST_SOURCE_HEALTH`, `LATEST_SNAPSHOT_VERSION` and `LAST_RUN_SUMMARY` — Key-Value records for API consumers.

### EU core source coverage

| Source | Jurisdiction | Access | Data semantics |
| --- | --- | --- | --- |
| Norway Finanstilsynet Short Sale Register | Norway | Official public API, NLOD 2.0 | Current public significant net-short positions |
| AMF open data | France | Daily official CSV, Open Licence 2.0 | Published significant net-short-position lifecycle history |
| AFM Net Short Positions | Netherlands | Official current CSV | Current public significant net-short positions |
| Bundesanzeiger Net Short Positions | Germany | Official session-backed CSV export | Current public net-short position register |
| Central Bank of Ireland Public Net Short Positions | Ireland | Official XLSX | Current public significant net-short positions |
| CNMV Posiciones Cortas | Spain | Official XLS | Current public net-short positions |

The Actor does **not** merge figures from different jurisdictions into a cross-market ranking. Every position-change event preserves the source-specific `source`, `jurisdiction`, `disclosure_type`, `effective_date` and publication-date fields.

For every adapter, the Actor reads a public regulator or regulator-supervised register. Public availability is not a statement that all jurisdictions have the same re-use licence: downstream consumers remain responsible for their own market-data, attribution and re-use obligations.

### Why integrate this Actor instead of building it internally

Downloading a regulator’s file once is straightforward. The engineering cost begins when a workflow needs to run reliably over time and when a regulator changes a file, a lifecycle rule, or a publication pattern.

| If a team builds internally | This Actor provides now | Boundary of this MVP |
| --- | --- | --- |
| Build and maintain a parser for each regulator | Six official-source adapters across the EU core | It does not claim universal EU or global coverage |
| Define how an initial import differs from a newly disclosed position | Explicit `BASELINE_POSITION` versus `NEW_POSITION` semantics | A baseline is not historical reconstruction |
| Store previous source state and compare it safely | Persistent per-`stateKey` snapshots and lifecycle classification | State is scoped to one Actor user and state key |
| Prevent an upstream outage from generating misleading closures | Per-source health records; failed sources retain their last known state | It cannot repair or validate an outage at the regulator |
| Invent a consumer contract and operational telemetry | Versioned event envelope, source fingerprints, run summary and API links | The consumer still owns retention, authorization and downstream business rules |

The value is therefore not an inaccessible dataset. It is a small managed integration boundary: a normalised change feed with evidence of what was read, when it was read, and whether one source failed. That lets a DMP, OMS-adjacent workflow, risk-control process or data team integrate without first creating and operating this plumbing.

It is deliberately a focused MVP, not a claim of an enterprise-grade SLA or universal market-data coverage. The durable product boundary is the common event contract and source-health model; future sources can be added as adapters without making cross-jurisdiction data appear comparable when it is not.

Where an official export contains multiple lifecycle rows for the same source, ISIN and position holder, the Actor selects the most recent dated observation before calculating state changes. `receivedPositionCount` reports raw adapter rows; `trackedPositionCount` reports the resulting distinct monitored positions.

### Run it as a monitor

Use the same `stateKey` for every scheduled run. Its snapshot is held in an independent named Key-Value Store rather than the per-run default store. First run produces a transparent baseline; later runs emit incremental change events.

```json
{
  "sources": ["norway", "france", "netherlands", "germany", "ireland", "spain"],
  "issuerKeywords": ["bank", "exchange", "financial"],
  "stateKey": "european-financial-sector-watch",
  "onlyChanges": true
}
```

Use `isins` when you need a strict instrument watchlist.

`historyRetentionRuns` controls how many snapshot-version metadata entries (default: 180) remain in the persistent store. Snapshot version metadata enables downstream consumers to identify the exact state used to create an event; it is not a substitute for an external regulatory archive.

### Integration pattern

1. Schedule a Task with a stable `stateKey`.
2. Configure an Apify Task webhook for a successful run.
3. The consumer receives the run reference, reads the Dataset, and advances its own checkpoint using `eventId` or `snapshotId`. The event identifier is monotonic within a `stateKey`; consumers that persist deliveries can additionally de-duplicate by `eventFingerprint`.

Events are suitable for a DMP, risk/compliance workflow or operational queue. Consumers should retain source provenance and apply their own entitlement, retention and regulatory policies.

The Actor publishes machine-readable output links for the event stream, last run summary, latest snapshot version and source health. Its Dataset provides focused views for change events, source health and run summaries. See [API consumer guide](docs/API.md) for response fields, run semantics and a checkpoint pattern.

### Data quality and interpretation

- Public disclosure is regulated data, not a real-time feed.
- A position absent from a public snapshot may reflect a threshold/lifecycle rule, not necessarily an economic position of zero.
- French AMF explicitly cautions that a published sub-0.5% row can remain visible as the last public disclosure rather than the investor’s current economic position.
- The Actor reports source facts and changes; it does not infer short squeezes, price direction, manipulation, or a trading recommendation.
- `POSITION_CLOSED` means the record is absent from the selected source snapshot. It never asserts that an underlying economic position is zero.
- A `FAILED` source-health record is an operational result, not a clean source snapshot. The Actor deliberately keeps its preceding state so a failed request cannot create false `POSITION_CLOSED` events.

### Development

```bash
pip install -r requirements.txt
pytest -q
python -m src.main
```

Set `APIFY_LOCAL_STORAGE_DIR` and provide an `INPUT.json` when running through the Apify local workflow.

# Changelog

This Actor's version history is a separate document: https://apify.com/highbrow\_qualification\_z7w/regulatory-short-position-change-layer/changelog.md

# Actor input Schema

## `sources` (type: `array`):

Official sources to query. Supported values: norway, france, netherlands, germany, ireland, spain.

## `isins` (type: `array`):

Optional ISINs. Leave empty to monitor all currently disclosed positions from selected sources.

## `issuerKeywords` (type: `array`):

Optional case-insensitive issuer-name filters.

## `stateKey` (type: `string`):

Use the same key on scheduled runs to compare with the prior snapshot.

## `onlyChanges` (type: `boolean`):

When enabled, unchanged positions are not written to the dataset.

## `maxInstruments` (type: `integer`):

Safety cap after filtering. 0 means no cap.

## `historyRetentionRuns` (type: `integer`):

Number of snapshot version metadata records retained in the persistent state store (1–1000).

## Actor input object example

```json
{
  "sources": [
    "norway",
    "france",
    "netherlands",
    "germany",
    "ireland",
    "spain"
  ],
  "isins": [],
  "issuerKeywords": [],
  "stateKey": "default",
  "onlyChanges": true,
  "maxInstruments": 0,
  "historyRetentionRuns": 180
}
```

# Actor output Schema

## `eventStream` (type: `string`):

Default Dataset containing position-change-event, source-health and run-summary records.

## `lastRunSummary` (type: `string`):

Operational outcome of the latest run, including counts and source errors.

## `latestSnapshotVersion` (type: `string`):

Version metadata and fingerprints for the snapshot used to create the current event stream.

## `latestSourceHealth` (type: `string`):

Per-source retrieval status, counts and fingerprints for the latest run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("highbrow_qualification_z7w/regulatory-short-position-change-layer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("highbrow_qualification_z7w/regulatory-short-position-change-layer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call highbrow_qualification_z7w/regulatory-short-position-change-layer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,highbrow_qualification_z7w/regulatory-short-position-change-layer"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dDRsNhzQDGHjmi7cu/builds/tRutqrv4Xoge8Cvnt/openapi.json
