41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
import hashlib
|
|
from typing import List
|
|
from dataclasses import dataclass
|
|
|
|
from .primitives import LocalArbProblem, SharedSignals
|
|
|
|
|
|
@dataclass
|
|
class PlanDelta:
|
|
legs: List[dict]
|
|
total_size: float
|
|
delta_id: str
|
|
|
|
|
|
def _deterministic_id(inputs: List[LocalArbProblem], shared: SharedSignals) -> str:
|
|
# Create a stable representation of inputs for deterministic hashing
|
|
parts = []
|
|
for lp in sorted(inputs, key=lambda x: (x.asset_pair[0], x.asset_pair[1])):
|
|
parts.append(
|
|
f"{lp.asset_pair}:{lp.target_mispricing}:{lp.liquidity_budget}:{lp.latency_budget}"
|
|
)
|
|
s = "|".join(parts) + f"|shared:{shared.cross_venue_corr}:{shared.latency_proxy}"
|
|
return hashlib.sha256(s.encode("utf-8")).hexdigest()
|
|
|
|
|
|
def admm_lite_step(local_problems: List[LocalArbProblem], shared_signals: SharedSignals) -> PlanDelta:
|
|
# Deterministic, simple projection: create one leg per local problem
|
|
legs = []
|
|
# deterministic order by asset_pair
|
|
for lp in sorted(local_problems, key=lambda x: (x.asset_pair[0], x.asset_pair[1])):
|
|
leg_size = max(0.0, float(lp.liquidity_budget) * 0.01)
|
|
legs.append({
|
|
"asset_pair": list(lp.asset_pair),
|
|
"size": leg_size,
|
|
"venue": "default",
|
|
})
|
|
|
|
total_size = float(sum(lp.liquidity_budget for lp in local_problems)) * 0.01 if local_problems else 0.0
|
|
delta_id = _deterministic_id(local_problems, shared_signals)
|
|
return PlanDelta(legs=legs, total_size=total_size, delta_id=delta_id)
|