Skip to content

feat(options-gps): autonomous execution engine#43

Open
eureka928 wants to merge 6 commits intoentrius:mainfrom
eureka928:feature/issue-26-autonomous-execution
Open

feat(options-gps): autonomous execution engine#43
eureka928 wants to merge 6 commits intoentrius:mainfrom
eureka928:feature/issue-26-autonomous-execution

Conversation

@eureka928
Copy link
Contributor

@eureka928 eureka928 commented Mar 13, 2026

Summary

Adds a full autonomous execution engine to Options GPS — the CLI can now place, monitor, and manage option orders on Deribit and Aevo directly from the terminal. Dry-run mode simulates execution with zero credentials. No changes to pipeline.py or exchange.py — the executor is a clean new module that consumes their data classes.

Closes #26

What Changed

executor.py — Execution engine (930 lines)

Data model:

  • OrderRequest / OrderResult / ExecutionPlan / ExecutionReport dataclasses
  • OrderResult tracks timestamp, slippage_pct, latency_ms per fill
  • ExecutionPlan supports max_slippage_pct, max_loss_usd, timeout_seconds, size_multiplier

Executor hierarchy (BaseExecutor ABC → 3 implementations):

  • DryRunExecutor — stateful offline simulation; tracks orders in _orders dict for get_order_status() / cancel_order() lifecycle
  • DeribitExecutor — JSON-RPC 2.0 with Bearer token auth, USD→BTC price conversion via _get_index_price(), live order book snapping via _get_book_price() with mark_price fallback, tick-size alignment (0.0005 BTC), retry on transient errors (429/502/503) with exponential backoff
  • AevoExecutor — REST with correct 4-part HMAC-SHA256 signing (method + path + timestamp + body), retry with exponential backoff

Full order lifecycle: place_order()_monitor_order() (poll until filled/timeout) → cancel_order() on timeout → get_order_status() returns OrderResult (not string)

Orchestration:

  • build_execution_plan() — auto-routes each leg to best venue via leg_divergences(), builds exchange-specific instrument names (Deribit: BTC-26FEB26-67500-C, Aevo: BTC-67500-C), applies size multiplier
  • validate_plan() — pre-flight checks + max-loss budget validation
  • execute_plan() — sequential fill with slippage protection, auto-cancel filled legs on partial failure, per-fill timestamps/latency
  • compute_execution_savings() — compares actual fill cost vs Synth theoretical price
  • save_execution_log() / load_execution_log() — JSON audit trail

main.py — CLI integration (+198 lines)

Flag Purpose
--execute [best|safer|upside] Submit live orders for chosen card
--dry-run [best|safer|upside] Simulate execution (no API keys needed)
--exchange deribit|aevo Force venue (default: auto-route per leg)
--force Override no-trade guardrail
--size N Position size multiplier
--max-slippage PCT Halt if any fill exceeds slippage %
--max-loss USD Pre-trade risk budget check
--timeout SECS Order monitoring timeout (default 30s)
--log-file PATH Save execution report JSON
--screen none Skip analysis screens, show only execution

Screen 5 (Execution): order plan, confirmation prompt (live), per-leg results with slippage/latency, auto-cancelled orders, execution savings vs Synth theoretical.

Guardrail: _refuse_execution() — extracted testable function; blocks live when no-trade is active unless --force.

README.md — Full documentation

Exchange integration architecture, all CLI flags, env vars, protocol details (Deribit USD→BTC conversion, order book snapping with mark_price fallback, tick alignment; Aevo 4-part HMAC signing).

Type of Change

  • Improvement to existing tool

Testing

  • Manually tested
  • Tests added/updated

python -m pytest tools/options-gps/tests/ -v211 passed (119 existing + 92 new)

Test breakdown

test_executor.py — 83 tests, 591 lines, 14 classes:

Class Tests Covers
TestInstrumentNames 7 Deribit/Aevo name builders, roundtrip, edge cases
TestBuildPlan 8 Single/multi-leg, exchange override, auto-route, estimated cost, size multiplier
TestValidatePlan 7 Valid plan, empty orders, zero price/qty, empty instrument, max-loss budget
TestDryRunExecutor 10 Auth, buy/sell fills, missing strike, fallback, stateful order tracking, cancel lifecycle
TestExecuteFlow 8 Single/multi-leg, net cost, summary, timestamps, timeout, factory routing
TestGetExecutor 5 Dry-run, exchange override, missing creds, unknown exchange
TestSlippage 8 Buy/sell worse/better, zero expected, protection rejects/allows, multi-leg halt
TestExecutionLog 1 Save + load roundtrip
TestRetryable 5 429/502/503 retry, success pass-through, non-retryable raise
TestMonitoringAndCancel 7 Timeout→cancel, delayed fill, rejected terminal, auto-cancel filled legs
TestExecutionSavings 3 Cheaper/same/multi-leg savings computation
TestAevoSigning 3 4-part HMAC signature, headers, empty body
TestDeribitPriceConversion 4 Tick alignment, USD→BTC conversion, fallback, index cache
TestCLI 5 --screen none/0/all, _refuse_execution blocks/allows

test_executor_e2e.py — 9 tests, 269 lines:

  • Full pipeline → dry-run execution (single-leg + multi-leg)
  • Auto-routing with factory callable
  • Execution report timing (started_at, finished_at, per-fill timestamps)
  • Guardrail: blocks live, allows --force, allows dry-run, allows when no guardrail
  • Non-crypto symbol returns no exchange data

Edge Cases Handled

# Scenario Behavior
1 No API credentials get_executor raises with clear env var message
2 Non-crypto + execute Exit 1: "Execution only supported for crypto"
3 No exchange quotes Exit 1: "exchange data not available"
4 Multi-leg partial failure Auto-cancel filled legs; warn about manual close
5 Order timeout Poll → cancel → report timeout status
6 Slippage exceeds limit Reject fill, cancel remaining, warn about filled legs
7 Max loss exceeded Reject plan before any orders sent
8 No-trade guardrail active Block live unless --force; dry-run always allowed
9 Order book empty (no bid/ask) Fall back to mark_price from order book response
10 Transient API errors (429/502/503) Retry with exponential backoff (3 attempts)
11 Deribit USD pricing Convert to BTC via index price, snap to tick size
12 Default CLI (no execute flags) Unchanged — analysis screens only

Diff vs existing codebase

File Status Lines Purpose
executor.py New 930 Execution engine
main.py Modified +198 CLI flags + Screen 5
tests/test_executor.py New 591 83 unit tests
tests/test_executor_e2e.py New 269 9 E2E tests
README.md Modified +73 Docs

Not modified: pipeline.py, exchange.py, requirements.txt

Environment Variables (live execution only)

Variable Purpose
DERIBIT_CLIENT_ID / DERIBIT_CLIENT_SECRET Deribit API credentials
DERIBIT_TESTNET=1 Use Deribit testnet
AEVO_API_KEY / AEVO_API_SECRET Aevo API credentials
AEVO_TESTNET=1 Use Aevo testnet

None needed for --dry-run.

CLI Output: --symbol BTC --view bullish --risk medium --dry-run

Screen 5: Execution (dry-run)
┌── Screen 5: Execution ─────────────────────────────────────────────────┐
│  Mode: DRY RUN
│  Exchange: AUTO
│  Asset: BTC
│  Strategy: Long call (ATM)
│
│  ═══ ORDER PLAN ════════════════════════════════════════
│    Leg 0: BUY 1x BTC-67500-C @ $655.00 (limit) [aevo]
│
│    Est. Cost:.......... $655.00
│    Est. Max Loss:...... $638.43
│
│  ═══ RESULTS ═══════════════════════════════════════════
│    ✓ BUY BTC-67500-C: simulated @ $655.00 x1
│
│    All Filled:......... Yes
│    Net Cost:........... $655.00
│    Started:............ 2026-03-13T23:05:54+00:00
│    Finished:........... 2026-03-13T23:05:54+00:00
│    Savings vs Synth:... $-16.57 (-2.6%)
│  All 1 legs simulated successfully. Net cost: $655.00
└────────────────────────────────────────────────────────────────────────┘
Full 5-screen output
┌── Screen 1: View Setup ────────────────────────────────────────────────┐
│  Symbol: BTC (from --symbol)
│  View: bullish (from --view)
│  Risk: medium (from --risk)
│
│  ════════════════════════════════════════════════════════════
│    ▲ BTC  BULLISH  MEDIUM RISK
│  ════════════════════════════════════════════════════════════
│    Strategy scan : directional long/spread
│    Risk profile  : balanced risk/reward
│    Data sources  : Synth 1h + 24h forecasts, option pricing
└────────────────────────────────────────────────────────────────────────┘

┌── Market Context: BTC ─────────────────────────────────────────────────┐
│    Price:.............. $67,723.50
│    Confidence:......... [███████░░░░░░░░░░░░░░░░░░] 29% LOW
│    Forecast fusion:.... Unclear (1h + 24h)
│    Volatility:......... fwd 62.4% / realized 56.6% (ratio 1.10x) [Normal]
│
│  ═══ MARKET LINE SHOPPING ══════════════════════════════
│      Strike                     CALL                   │                   PUT
│                  Synth    DER    AEV     * Exec   Edge │   Synth    DER    AEV     * Exec   Edge
│    ─────────────────────────────────────────────────────────────────────────────────────────────
│      67,000        987    988    985  AEV 1,010  +0.7σ │     140    141    142  AEV   148  -1.9σ
│      67,500 ◀      638    635    638  AEV   655  +1.5σ │     292    292    292  AEV   305  -2.1σ
│      68,000        373    372    372  AEV   385  +2.1σ │     527    526    526  AEV   542  +0.6σ
│      68,500        197    198    198  AEV   205  -2.0σ │     850    850    850  AEV   870  +0.5σ
│    ─────────────────────────────────────────────────────────────────────────────────────────────
│    * Exec = best execution venue ask price (DER=Deribit, AEV=Aevo)
└────────────────────────────────────────────────────────────────────────┘

┌── Screen 2: Top Plays ─────────────────────────────────────────────────┐
│                                           ~Best                  ~Safer                 ~Upside
│                          ──────────────────────  ──────────────────────  ──────────────────────
│    Strategy                     Long call (ATM)  Bull put credit spread         Long call (OTM)
│    PoP                                      46%                     55%                     40%
│    Expected Value                  $542 (+0.8%)            $-58 (-0.1%)            $498 (+0.7%)
│    Max Loss                                $638                    $349                    $197
└────────────────────────────────────────────────────────────────────────┘

┌── Screen 5: Execution ─────────────────────────────────────────────────┐
│  Mode: DRY RUN  |  Exchange: AUTO  |  Asset: BTC
│  Strategy: Long call (ATM)
│
│  ═══ ORDER PLAN ════════════════════════════════════════
│    Leg 0: BUY 1x BTC-67500-C @ $655.00 (limit) [aevo]
│    Est. Cost: $655.00  |  Est. Max Loss: $638.43
│
│  ═══ RESULTS ═══════════════════════════════════════════
│    ✓ BUY BTC-67500-C: simulated @ $655.00 x1
│    All Filled: Yes  |  Net Cost: $655.00
│    Savings vs Synth: $-16.57 (-2.6%)
└────────────────────────────────────────────────────────────────────────┘

Demo Video

Coming soon

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Changes are documented

Add --execute, --dry-run, and --exchange CLI flags with Screen 5 execution UI.
Supports Deribit and Aevo via ABC executor pattern with dry-run simulation.
37 new tests (156 total passing), no changes to pipeline.py or exchange.py.
@eureka928 eureka928 force-pushed the feature/issue-26-autonomous-execution branch from 8d11b7d to c0eb4ca Compare March 13, 2026 18:17
@eureka928 eureka928 changed the title feat(options-gps): autonomous execution engine (closes #26) feat(options-gps): autonomous execution engine Mar 13, 2026
- Order monitoring: poll open orders until filled/timeout, auto-cancel on timeout
- Auto-cancel: cancel already-filled legs when a later leg fails (partial fill safety)
- Execution savings: compare auto-routed cost vs Synth theoretical price
- Aevo HMAC-SHA256: fix to 4-part signing (timestamp+method+path+body)
- Timestamps & latency: ISO 8601 timestamps and round-trip latency on every fill
- --timeout CLI flag: configurable order monitoring timeout (default 30s)
- Screen 5 enhancements: show latency, timestamps, cancelled orders, savings
- Decision log: include slippage, timestamps, latency, cancelled orders per fill
- 210 tests passing (29 new): monitoring, auto-cancel, savings, HMAC, guardrails
@eureka928 eureka928 force-pushed the feature/issue-26-autonomous-execution branch from 38273d8 to 308879e Compare March 13, 2026 21:53
- Deribit price conversion: _get_index_price() fetches USD index (cached),
  _usd_to_btc() converts pipeline USD prices, _get_book_price() snaps to
  live order book, _align_tick() rounds to 0.0005 BTC tick size
- Stateful DryRunExecutor: tracks placed orders in _orders dict,
  get_order_status() returns stored OrderResult, cancel_order() transitions
  state to "cancelled", unknown IDs return "not_found"
- get_order_status() returns OrderResult across all executors (richer type)
- _monitor_order() returns OrderResult with fill data, updates result in
  execute_plan with fill_price/fill_quantity from monitoring
- --screen none/0: skip all analysis screens, show only execution (Screen 5)
- _refuse_execution(): extracted testable guardrail function
- 230 tests passing (20 new): tick alignment, USD→BTC, stateful executor,
  screen parsing, refuse_execution, OrderResult return type
When best_ask/best_bid is unavailable (empty order book), falls back
to mark_price from Deribit order book response before returning None.
Merge related test classes, remove redundant coverage, trim edge-case
tests already covered by integration tests.  83 tests, 211 total suite.
@ventura-oss
Copy link

Testing live execution on Aevo currently fails with a 401 Unauthorized error. The implementation only uses the basic REST API key headers for authentication, but placing orders on Aevo requires Layer 2 (L2) cryptographic signing, which is completely missing from this execution engine.

AevoExecutor now signs orders with EIP-712 typed data using eth-account,
matching Aevo's OP Stack L2 settlement architecture. Adds instrument ID
resolution, 6-decimal fixed-point pricing, and proper order payload format.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Options GPS: Autonomous Execution

2 participants