Skip to content

How To Add A Market Adapter

euroflex_bess_lab treats the market layer as a plugin-style contract. A new adapter should let the rest of the stack keep the same shape:

  • configs stay schema_version: 4
  • walk-forward still runs through run_walk_forward()
  • compare/sweep still consume the stable artifact contract
  • reserve-aware workflows can query the adapter for supported reserve products
  • portfolio runs continue to use site-level market data and asset-level dispatch outputs
  • schedule_revision continues to route settlement and timing through revision.base_workflow

Public imports should go through euroflex_bess_lab.markets or the package root. markets/adapters/ is the implementation layer, not the preferred import path for user code.

Adapter checklist

Create a new file under src/euroflex_bess_lab/markets/adapters/ and implement MarketAdapter:

class MarketAdapter:
    market_id: str
    timezone: str
    resolution_minutes: int
    supported_workflows: tuple[str, ...]

    def load_actuals(self, config): ...
    def validate_timing(self, config): ...
    def decision_schedule(self, config): ...
    def settlement_engine(self, workflow): ...
    def default_benchmarks(self): ...
    def supported_reserve_products(self): ...
    def build_reserve_product(self, config): ...

Practical steps

  1. Add the adapter implementation.
  2. Reuse load_input_series() from the base adapter.
  3. Enforce market timezone and resolution in validate_timing().
  4. Return the right settlement engine for each execution workflow.
  5. If the market supports reserve-lite benchmarks, expose them through supported_reserve_products() and build_reserve_product().
  6. Make sure revision runs behave correctly when config.execution_workflow differs from config.workflow.

  7. Register the adapter.

  8. Add it to src/euroflex_bess_lab/markets/adapters/registry.py.
  9. Users select --market and --workflow explicitly.

  10. Add normalized fixtures.

  11. Put frozen sample CSVs in examples/data/.
  12. If live ingestion needs auth, document the env vars in the example config.
  13. Prefer raw fixture samples under tests/fixtures/raw/ for normalization tests.

  14. Add example configs.

  15. Create basic/<market>_da_only_base.yaml.
  16. If publicly supported, add a curated example only when it belongs in the promoted example surface.
  17. If reserve-lite is supported, add reserve/<market>_da_plus_fcr_base.yaml.
  18. If expected-value aFRR is supported, add reserve/<market>_da_plus_afrr_base.yaml.
  19. If portfolio workflows are supported, add basic/<market>_portfolio_da_only_base.yaml, reserve/<market>_portfolio_da_plus_fcr_base.yaml, and any honest da_plus_afrr portfolio examples.
  20. If revision is supported, add basic/<market>_schedule_revision_da_only_base.yaml and any reserve-aware revision examples you can support honestly.

  21. Add tests.

  22. Adapter contract test
  23. Walk-forward smoke test
  24. Artifact contract test
  25. CLI smoke test if you add ingestion or a new workflow
  26. Notebook or docs smoke test if the new adapter ships with a tutorial