|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
|
|
|
import argparse
|
|
|
import json
|
|
|
+import os
|
|
|
import sys
|
|
|
from dataclasses import asdict
|
|
|
from datetime import UTC, datetime
|
|
|
@@ -61,10 +62,13 @@ def account_current_position(margin_per_unit_usdt: float) -> tuple[TargetPositio
|
|
|
return unknown_current_position(str(exc)), {"account_error": str(exc)}
|
|
|
|
|
|
|
|
|
-def build_snapshot(*, state_dir: Path, margin_per_unit_usdt: float, max_new_margin_usdt: float) -> dict[str, object]:
|
|
|
+EXECUTOR_STATE_FILENAME = "executor-runtime-state.json"
|
|
|
+
|
|
|
+
|
|
|
+def build_snapshot(*, state_dir: Path, margin_per_unit_usdt: float, max_new_margin_usdt: float, max_total_margin_usdt: float) -> dict[str, object]:
|
|
|
state_dir.mkdir(parents=True, exist_ok=True)
|
|
|
payload = eth_nextgen_micro.build_payload()
|
|
|
- previous_state = load_runtime_state(state_dir / "runtime-state.json")
|
|
|
+ previous_state = load_runtime_state(state_dir / EXECUTOR_STATE_FILENAME)
|
|
|
next_state, target = target_from_signal(payload, previous_state)
|
|
|
current, account = account_current_position(margin_per_unit_usdt)
|
|
|
plan = plan_position_delta(current, target)
|
|
|
@@ -78,6 +82,7 @@ def build_snapshot(*, state_dir: Path, margin_per_unit_usdt: float, max_new_marg
|
|
|
leverage=LEVERAGE,
|
|
|
margin_per_unit_usdt=margin_per_unit_usdt,
|
|
|
max_new_margin_usdt=max_new_margin_usdt,
|
|
|
+ max_total_margin_usdt=max_total_margin_usdt,
|
|
|
client_order_id_prefix=f"ethnm-{target_candle_ts(payload)}",
|
|
|
)
|
|
|
return {
|
|
|
@@ -100,12 +105,22 @@ def build_snapshot(*, state_dir: Path, margin_per_unit_usdt: float, max_new_marg
|
|
|
"risk_limits": {
|
|
|
"submit_enabled": False,
|
|
|
"max_new_margin_usdt": max_new_margin_usdt,
|
|
|
+ "max_total_margin_usdt": max_total_margin_usdt,
|
|
|
"margin_per_unit_usdt": margin_per_unit_usdt,
|
|
|
"state_write_required_before_live": True,
|
|
|
},
|
|
|
}
|
|
|
|
|
|
|
|
|
+def risk_arg(value: float | None, env_name: str) -> float:
|
|
|
+ if value is not None:
|
|
|
+ return value
|
|
|
+ raw = os.environ.get(env_name)
|
|
|
+ if raw is None or raw == "":
|
|
|
+ raise ValueError(f"{env_name} is required")
|
|
|
+ return float(raw)
|
|
|
+
|
|
|
+
|
|
|
def target_candle_ts(payload: dict[str, object]) -> int:
|
|
|
if payload["decision"]["active_engine"] == "nextgen":
|
|
|
return int(payload["nextgen"]["data"]["decision_candle_ts"])
|
|
|
@@ -122,14 +137,16 @@ def client_metadata(account: dict[str, object]):
|
|
|
def main() -> int:
|
|
|
parser = argparse.ArgumentParser(description="Build ETH nextgen+micro live execution dry-run snapshot.")
|
|
|
parser.add_argument("--state-dir", type=Path, default=STATE_DIR)
|
|
|
- parser.add_argument("--margin-per-unit-usdt", type=float, required=True)
|
|
|
- parser.add_argument("--max-new-margin-usdt", type=float, required=True)
|
|
|
+ parser.add_argument("--margin-per-unit-usdt", type=float)
|
|
|
+ parser.add_argument("--max-new-margin-usdt", type=float)
|
|
|
+ parser.add_argument("--max-total-margin-usdt", type=float)
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
snapshot = build_snapshot(
|
|
|
state_dir=args.state_dir,
|
|
|
- margin_per_unit_usdt=args.margin_per_unit_usdt,
|
|
|
- max_new_margin_usdt=args.max_new_margin_usdt,
|
|
|
+ margin_per_unit_usdt=risk_arg(args.margin_per_unit_usdt, "ETH_NEXTGEN_MARGIN_PER_UNIT_USDT"),
|
|
|
+ max_new_margin_usdt=risk_arg(args.max_new_margin_usdt, "ETH_NEXTGEN_MAX_NEW_MARGIN_USDT"),
|
|
|
+ max_total_margin_usdt=risk_arg(args.max_total_margin_usdt, "ETH_NEXTGEN_MAX_TOTAL_MARGIN_USDT"),
|
|
|
)
|
|
|
print(json.dumps(snapshot, indent=2, sort_keys=True))
|
|
|
return 0
|