Skip to main content

Data Abstraction Layer — MIF ecosystem

Project description

MIF-DAL — Data Abstraction Layer

tests version python license

mif-dal is the data assembly layer of the MIF ecosystem. It fetches OHLCV market data from external sources, certifies it through mif-dqf, and delivers an immutable, hash-anchored result ready for metric computation.


Why mif-dal?

Quantitative research fails silently when its data foundation is uncertain. A strategy that looks profitable on Yahoo Finance data may behave differently on Kraken data — same asset, different gaps, different fills, different hashes.

mif-dal makes data provenance explicit and mandatory:

  • Every stream carries a assembly_hash (SHA-256 of raw bytes before any transformation). Two calls with the same parameters produce the same hash, or the difference is auditable.
  • Physical validity is guaranteed by mif-dqf before any data reaches your computation layer.
  • Source fallback is recorded, not hidden. If Kraken was unavailable and Yahoo was used instead, that decision is in the source_manifest.
  • The output — DALHandoff — is frozen. It cannot be mutated after emission.

The MIF Ecosystem

External data sources
        ↓
[mif-dal]   assembles stream, computes assembly_hash, delegates to mif-dqf
        ↓ DALHandoff
[mif-dqf]   certifies physical validity (OHLCV physics, calendar, gaps)
        ↓ DQFReport embedded in DALHandoff
[mif-core]  certifies metric/signal integrity (planned)
        ↓ MIFCertification
[QAAF Studio]  research layer (QS-PAF, QS-MÉTIS)

mif-dal sits between your data sources and your computation. It does not evaluate strategies. It does not qualify asset pairs. It answers one question: "Can I assemble a reproducible, certified OHLCV stream from available sources for this asset and date range?"


Installation

pip install mif-dal

Requires Python 3.11+ and mif-dqf >= 1.2.0 (installed automatically).

Optional: Dukascopy adapter

The Dukascopy adapter requires Node.js and dukascopy-node:

npm install -g dukascopy-node

Quick Start

from dal import DAL, DALConfig

config = DALConfig()
dal = DAL(config)

# One call per asset — caller composes the pair (architectural decision D-DAL-007)
h_paxg = dal.get_certified_stream(
    asset_id="PAXG-USD",
    source_preference=["kraken", "yahoo"],
    start="2024-01-01",
    end="2024-12-31",
    calendar="CRYPTO_247",
    dqf_version_target="1.2.0",
)

h_btc = dal.get_certified_stream(
    asset_id="BTC-USD",
    source_preference=["kraken", "yahoo"],
    start="2024-01-01",
    end="2024-12-31",
    calendar="CRYPTO_247",
    dqf_version_target="1.2.0",
)

# Caller constructs the ratio
prices_pair = h_paxg.stream["close"] / h_btc.stream["close"]

print(f"DQF status : {h_paxg.dqf_status} / {h_btc.dqf_status}")
print(f"AQI        : {h_paxg.aqi:.0f} / {h_btc.aqi:.0f}")
print(f"Hash PAXG  : {h_paxg.assembly_hash[:16]}...")
print(f"Hash BTC   : {h_btc.assembly_hash[:16]}...")

Diagnostic mode (exploratory, no version enforcement)

h = dal.get_diagnostic_stream(
    asset_id="BTC-USD",
    source_preference=["yahoo"],
    start="2023-01-01",
    end="2023-12-31",
    calendar="CRYPTO_247",
)
print(h.dqf_report)

The DALHandoff Object

Every successful call returns a DALHandoff — a frozen dataclass with 15 fields:

Field Type Description
stream pd.DataFrame OHLCV, UTC DatetimeIndex, no NaN, sorted ascending
asset_id str e.g. "PAXG-USD"
calendar str e.g. "CRYPTO_247", "NYSE"
assembly_hash str SHA-256 of raw bytes before any transformation
handoff_timestamp datetime UTC emission time
dal_version str mif-dal package version
source_manifest tuple Immutable record of sources used and fallback chain
coverage str FULL / PARTIAL / DEGRADED
truncated_days int 0 if FULL
dqf_status str PASS or WARNING
dqf_mpi float MIF Purity Index 0–100 (from mif-dqf)
dqf_version str mif-dqf version used
dqf_version_target str Minimum version declared by caller
dqf_report DQFReport Full mif-dqf report
aqi float Assembly Quality Index 0–100

DALHandoff is frozen=True. It cannot be mutated after emission.


Assembly Quality Index (AQI)

AQI measures how much intervention was required to assemble the stream. 100 = preferred source, full range, no retries. Lower = more intervention.

AQI Label Meaning
100 EXCELLENT Preferred source, full range, no retries
80–99 GOOD Minor fallback or single retry
60–79 ADVISORY Fallback + partial range
< 60 REVIEW Heavy intervention — investigate

AQI is on the D-SIG Standard v0.5 0–100 scale and can be used directly as a dimensions entry in a D-SIG signal.


Available Sources

Source Adapter Assets Notes
Kraken KrakenAdapter Crypto pairs Data available ~last 12 months
Yahoo Finance YahooAdapter Equities, ETFs, Crypto Broad coverage, variable quality
Dukascopy DukascopyAdapter Forex, Crypto Requires dukascopy-node
In-memory InMemorySource Any Testing and research

Error Handling

from dal.exceptions import DALHandoffError, DALVersionError, DALConfigError

try:
    h = dal.get_certified_stream(...)
except DALConfigError as e:
    # Missing or invalid configuration (e.g. calendar omitted)
    print(e)
except DALVersionError as e:
    # Installed mif-dqf < dqf_version_target
    print(e)
except DALHandoffError as e:
    # DQF returned VOID, or all sources failed
    print(e.reason)          # "DQF_VOID" | "ALL_SOURCES_FAILED"
    print(e.source_failures) # list of per-source error details

Errors are atomic: either a complete DALHandoff is returned, or an exception is raised. There is no partial or degraded return value.


Development

git clone https://github.com/symbioticode/mif-dal.git
cd mif-dal
uv sync --extra dev
./scripts/dev.sh check   # Ruff + Mypy + Pytest

Running tests

# Without network (fast, CI-suitable)
pytest tests/ -q

# With real network (Kraken, Yahoo, Dukascopy)
pytest tests/ --run-network

Validation

python scripts/validate_dal_state.py          # Quick GO/NO-GO
python scripts/validate_dal_state.py --full   # Full adversarial suite (65 checks)

Documentation

Document Description
docs/API.md Full public API reference
docs/ARCHITECTURE.md Pipeline, decisions, component map
docs/TROUBLESHOOTING.md Common issues (Kraken limits, NixOS, Dukascopy)
docs/DAL_SPECIFICATION_v1.0.md Formal specification — source of truth

Relationship to mif-dqf

mif-dal depends on mif-dqf for physical data validation. mif-dal calls mif-dqf internally — you do not need to call mif-dqf directly when using mif-dal.

The assembly_hash computed by mif-dal is passed to mif-dqf as raw_data_hash, so both layers anchor on the same SHA-256 value. The MIF-UID produced by mif-dqf is included in DALHandoff.dqf_report.


License

MIT — see LICENSE.

Part of the MIF ecosystem by symbioticode.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mif_dal-0.1.1.tar.gz (85.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mif_dal-0.1.1-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

Details for the file mif_dal-0.1.1.tar.gz.

File metadata

  • Download URL: mif_dal-0.1.1.tar.gz
  • Upload date:
  • Size: 85.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for mif_dal-0.1.1.tar.gz
Algorithm Hash digest
SHA256 280a282c4d4a1460472e2523d30337425679256f74334ae53eccf3489544e974
MD5 4601890c1a63637d0be4f3ecb8537a19
BLAKE2b-256 fbcc09a29f9152f1c52e10995b7e78dfed52c747989758b84595a03143f9ec0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for mif_dal-0.1.1.tar.gz:

Publisher: mif-dal-publish.yml on symbioticode/mif-dal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mif_dal-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mif_dal-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 27.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for mif_dal-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0b020b6d377ae6f31cc66735a1244728256ccb04ee4a47dd8178996c2995df83
MD5 11f6cb33b5c5a9c6d6ca31aa8fc83957
BLAKE2b-256 5c59137c93ec19ba76e03c18572ef0c616c2fea2413549c1a12880b1883318d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for mif_dal-0.1.1-py3-none-any.whl:

Publisher: mif-dal-publish.yml on symbioticode/mif-dal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page