norn
A small framework for market-data strategies (OHLCV → signal) and interpreters (signal → position changes). norn owns the contracts, a name registry, a typed error hierarchy and structured logging. It has no data-provider dependency — market data is the caller's to supply.
from norn.strategies import SMACrossoverStrategy
from norn.interpreter import BuyAndHoldInterpreter
# `ohlcv` is a Polars DataFrame with the norn.schema.OHLCV column names.
signals = SMACrossoverStrategy({"fast": 10, "slow": 30}).run(ohlcv)
operations = BuyAndHoldInterpreter().run(ohlcv, signals)
run() is symmetric by input type: pass Polars frames to get a frame back,
or pass sequences of the norn.contracts dataclasses to get a list back.
from norn.contracts import bars_from_frame
bars = bars_from_frame(ohlcv) # list[OHLCVBar]
points = SMACrossoverStrategy({"fast": 10}).run(bars) # list[SignalPoint]
operations = BuyAndHoldInterpreter().run(bars, points) # list[Operation]
Don't know the class ahead of time? Look it up by name in the registry:
from norn.strategies import STRATEGY_REGISTRY
signals = STRATEGY_REGISTRY.get("sma_crossover")({"fast": 10, "slow": 30}).run(ohlcv)
Concepts
| contract | input → output | |
|---|---|---|
| Strategy | norn.strategies.BaseStrategy |
OHLCV → date, ticker, signal (signal ∈ [-1, 1]) |
| Interpreter | norn.interpreter.BaseInterpreter |
OHLCV + signals → target_position (∈ [-1, 1]) and the position changes as operation_side / operation_pct |
Frame form uses the canonical column names in norn.schema (OHLCV, SIGNAL);
object form uses the dataclasses in norn.contracts (OHLCVBar, SignalPoint,
Operation). An interpreter always needs the OHLCV data alongside the signals.
The Operation list holds only the bars where the position actually moves.
Built-ins: strategies sma_crossover, rsi_mean_reversion; interpreters
signal_following, buy_and_hold.
sandbox/
A dev playground — not part of the package. sandbox/run_sma.py is a worked
example of the OHLCV → signals → operations path. It fetches live data with
heimdall-mimird (a dev-only
dependency), so it needs network access:
uv run python sandbox/run_sma.py
Extending
Add a strategy or interpreter in your own package and expose it through an entry
point so pip install is all a user needs. See CONTRIBUTING.md.
Development
uv sync
uv run pytest
uv run ruff check . && uv run ruff format --check .
uv run mypy
Metadata
Release files for norn-mimird 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| norn_mimird-0.3.0.tar.gz | 155.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| norn_mimird-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 177.6 kB
Release files / norn_mimird-0.3.0.tar.gz
| Download URL | norn_mimird-0.3.0.tar.gz |
|---|---|
| Size | 155.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cde2be8c8f3a6bf7e90295df36646e4ba99fd9d9e0a89d4d0dc36719230dd89d
|
|
BLAKE2b-256 checksum How to use checksums |
ce8ea1466e3e43e7dd504000ecfe649b2771404a02173c7e96310b4725b0d5f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Omarchy","version":"4.0.2","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / norn_mimird-0.3.0-py3-none-any.whl
| Download URL | norn_mimird-0.3.0-py3-none-any.whl |
|---|---|
| Size | 22.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e8f5fc17ef0e4faef25c9831117694242ce00686f3ef665529d3b5d3052dd25c
|
|
BLAKE2b-256 checksum How to use checksums |
7edcbec149af39cdcbbc6046e58c7ef8aae09e25f48c6f0bcd51afac29d3d488
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Omarchy","version":"4.0.2","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|