run_replay.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. from __future__ import annotations
  2. from pathlib import Path
  3. import argparse
  4. import json
  5. import sys
  6. ROOT = Path(__file__).resolve().parents[1]
  7. SRC = ROOT / "src"
  8. SIM_SRC = ROOT / "simulation" / "src"
  9. for path in (str(SRC), str(SIM_SRC)):
  10. if path not in sys.path:
  11. sys.path.insert(0, path)
  12. from hermes_sim.candles import load_candles_csv
  13. from hermes_sim.harness import ReplayConfig, rows_to_jsonl, run_replay
  14. def main() -> int:
  15. parser = argparse.ArgumentParser(description="Replay Hermes decisions from historic candles.")
  16. parser.add_argument("--candles", required=True, help="Path to a CSV with timestamp,open,high,low,close,volume columns")
  17. parser.add_argument("--symbol", default="XRPUSD")
  18. parser.add_argument("--base", default="XRP")
  19. parser.add_argument("--quote", default="USD")
  20. parser.add_argument("--account-id", default="sim-account")
  21. parser.add_argument("--fee-rate", type=float, default=0.004)
  22. parser.add_argument("--horizon-bars", type=int, default=30)
  23. parser.add_argument("--base-balance", type=float, default=500.0)
  24. parser.add_argument("--quote-balance", type=float, default=500.0)
  25. parser.add_argument("--inventory-state", default="balanced")
  26. parser.add_argument("--rebalance-needed", action="store_true")
  27. parser.add_argument("--out", help="Optional JSONL output file")
  28. args = parser.parse_args()
  29. candles = load_candles_csv(args.candles)
  30. config = ReplayConfig(
  31. market_symbol=args.symbol,
  32. base_currency=args.base,
  33. quote_currency=args.quote,
  34. account_id=args.account_id,
  35. fee_rate=args.fee_rate,
  36. horizon_bars=args.horizon_bars,
  37. base_balance=args.base_balance,
  38. quote_balance=args.quote_balance,
  39. inventory_state=args.inventory_state,
  40. rebalance_needed=args.rebalance_needed,
  41. )
  42. rows = run_replay(candles=candles, config=config)
  43. output = rows_to_jsonl(rows)
  44. if args.out:
  45. Path(args.out).write_text(output + ("\n" if output else ""), encoding="utf-8")
  46. else:
  47. print(output)
  48. summary = {
  49. "candles": len(candles),
  50. "rows": len(rows),
  51. "avg_score": round(sum(r.score for r in rows) / len(rows), 4) if rows else 0.0,
  52. }
  53. print(json.dumps(summary, indent=2), file=sys.stderr)
  54. return 0
  55. if __name__ == "__main__":
  56. raise SystemExit(main())