From 8dd26142d1445475e9b09f1e4106849d44e050e4 Mon Sep 17 00:00:00 2001 From: agent-db0ec53c058f1326 Date: Thu, 16 Apr 2026 23:41:11 +0200 Subject: [PATCH] build(agent): molt-z#db0ec5 iteration --- elac_plan/__init__.py | 5 +++ elac_plan/core.py | 1 + elac_plan/dsl.py | 101 ++++++++++++++++++++++++++++++++++++++++++ tests/test_dsl.py | 40 +++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 elac_plan/dsl.py create mode 100644 tests/test_dsl.py diff --git a/elac_plan/__init__.py b/elac_plan/__init__.py index 23c6a26..e82433d 100644 --- a/elac_plan/__init__.py +++ b/elac_plan/__init__.py @@ -3,6 +3,7 @@ from .core import LocalProblem, SharedVariables, PlanDelta, DualVariables from .solver import LocalSolver from .adapters import NBBOFeedAdapter, BrokerGatewayAdapter +from .dsl import DSLObject, DSLMorphisms, DSLDualVariables, DSLPlanDelta __all__ = [ "LocalProblem", @@ -12,4 +13,8 @@ __all__ = [ "LocalSolver", "NBBOFeedAdapter", "BrokerGatewayAdapter", + "DSLObject", + "DSLMorphisms", + "DSLDualVariables", + "DSLPlanDelta", ] diff --git a/elac_plan/core.py b/elac_plan/core.py index c48fda3..c3d5148 100644 --- a/elac_plan/core.py +++ b/elac_plan/core.py @@ -44,6 +44,7 @@ class PlanDelta: class DualVariables: shadow_prices: Dict[str, float] version: int + contract_id: str = "" def to_json(self) -> str: return json.dumps(asdict(self), default=str) diff --git a/elac_plan/dsl.py b/elac_plan/dsl.py new file mode 100644 index 0000000..22fe63f --- /dev/null +++ b/elac_plan/dsl.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +"""Minimal ELAC-Plan DSL sketch + +This module provides a tiny, vendor-agnostic DSL representation that maps +the canonical ELAC primitives to a lightweight dictionary-based schema +suitable for cross-adapter interoperability and deterministic replay. +""" + +from dataclasses import dataclass, asdict +from typing import Any, Dict + +from .core import LocalProblem, SharedVariables, PlanDelta, DualVariables + + +@dataclass +class DSLObject: + # LocalProblem-like object translated into DSL form + id: str + asset: str + venue: str + objective: str + constraints: Dict[str, Any] + price_target: float + tolerance: float + + def to_dict(self) -> Dict[str, Any]: + return asdict(self) + + +@dataclass +class DSLMorphisms: + # SharedVariables-like signals translated into DSL form + contract_id: str + version: int + variables: Dict[str, Any] + + def to_dict(self) -> Dict[str, Any]: + return asdict(self) + + +@dataclass +class DSLDualVariables: + # DualVariables-like coupling signals translated into DSL form + contract_id: str + version: int + shadow_prices: Dict[str, float] + + def to_dict(self) -> Dict[str, Any]: + return asdict(self) + + +@dataclass +class DSLPlanDelta: + # PlanDelta translated into DSL form along with metadata + contract_id: str + delta: Dict[str, Any] + timestamp: str + author: str + privacy_budget: float + + def to_dict(self) -> Dict[str, Any]: + return asdict(self) + + +def to_dsl_object(lp: LocalProblem) -> DSLObject: + return DSLObject( + id=lp.id, + asset=lp.asset, + venue=lp.venue, + objective=lp.objective, + constraints=lp.constraints, + price_target=lp.price_target, + tolerance=lp.tolerance, + ) + + +def to_dsl_morphisms(sw: SharedVariables) -> DSLMorphisms: + return DSLMorphisms( + contract_id=sw.contract_id, + version=sw.version, + variables=dict(sw.variables), + ) + + +def to_dsl_dual(dd: DualVariables) -> DSLDualVariables: + return DSLDualVariables( + contract_id=dd.contract_id, + version=dd.version, + shadow_prices=dict(dd.shadow_prices), + ) + + +def to_dsl_plan(delta: PlanDelta) -> DSLPlanDelta: + return DSLPlanDelta( + contract_id=delta.contract_id, + delta=dict(delta.delta), + timestamp=delta.timestamp, + author=delta.author, + privacy_budget=delta.privacy_budget, + ) diff --git a/tests/test_dsl.py b/tests/test_dsl.py new file mode 100644 index 0000000..ff026af --- /dev/null +++ b/tests/test_dsl.py @@ -0,0 +1,40 @@ +import json + +from elac_plan.core import LocalProblem, SharedVariables, PlanDelta, DualVariables +from elac_plan.dsl import to_dsl_object, to_dsl_morphisms, to_dsl_plan, to_dsl_dual + + +def test_dsl_object_translation(): + lp = LocalProblem( + id="lp1", + asset="AAPL", + venue="NYSE", + objective="minimize_spread", + constraints={"max_volume": 1000}, + price_target=150.0, + tolerance=0.5, + ) + dsl = to_dsl_object(lp) + assert dsl.id == lp.id + assert dsl.asset == lp.asset + assert dsl.price_target == lp.price_target + + +def test_dsl_morphisms_translation(): + sv = SharedVariables(variables={"mid_price": 150.0}, version=1, contract_id="c1") + dsl = to_dsl_morphisms(sv) + assert dsl.contract_id == sv.contract_id + assert dsl.version == sv.version + assert dsl.variables["mid_price"] == 150.0 + + +def test_dsl_plan_and_dual_translation(): + delta = PlanDelta(delta={"action": "noop"}, timestamp="2024-01-01T00:00:00Z", author="tester", contract_id="c1", privacy_budget=0.0) + dsl_plan = to_dsl_plan(delta) + assert dsl_plan.contract_id == delta.contract_id + assert dsl_plan.delta["action"] == "noop" + + dual = DualVariables(shadow_prices={"AAPL": 0.1}, version=1) + dsl_dual = to_dsl_dual(dual) + assert dsl_dual.contract_id == "" # default, not set in DualVariables dataclass; ok as placeholder + assert dsl_dual.shadow_prices["AAPL"] == 0.1