feat(options-gps): autonomous execution engine#43
Open
eureka928 wants to merge 6 commits intoentrius:mainfrom
Open
feat(options-gps): autonomous execution engine#43eureka928 wants to merge 6 commits intoentrius:mainfrom
eureka928 wants to merge 6 commits intoentrius:mainfrom
Conversation
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.
8d11b7d to
c0eb4ca
Compare
- 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
38273d8 to
308879e
Compare
- 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.
|
Testing live execution on Aevo currently fails with a |
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.pyorexchange.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/ExecutionReportdataclassesOrderResulttrackstimestamp,slippage_pct,latency_msper fillExecutionPlansupportsmax_slippage_pct,max_loss_usd,timeout_seconds,size_multiplierExecutor hierarchy (
BaseExecutorABC → 3 implementations):DryRunExecutor— stateful offline simulation; tracks orders in_ordersdict forget_order_status()/cancel_order()lifecycleDeribitExecutor— 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 backoffAevoExecutor— REST with correct 4-part HMAC-SHA256 signing (method + path + timestamp + body), retry with exponential backoffFull order lifecycle:
place_order()→_monitor_order()(poll until filled/timeout) →cancel_order()on timeout →get_order_status()returnsOrderResult(not string)Orchestration:
build_execution_plan()— auto-routes each leg to best venue vialeg_divergences(), builds exchange-specific instrument names (Deribit:BTC-26FEB26-67500-C, Aevo:BTC-67500-C), applies size multipliervalidate_plan()— pre-flight checks + max-loss budget validationexecute_plan()— sequential fill with slippage protection, auto-cancel filled legs on partial failure, per-fill timestamps/latencycompute_execution_savings()— compares actual fill cost vs Synth theoretical pricesave_execution_log()/load_execution_log()— JSON audit trailmain.py— CLI integration (+198 lines)--execute [best|safer|upside]--dry-run [best|safer|upside]--exchange deribit|aevo--force--size N--max-slippage PCT--max-loss USD--timeout SECS--log-file PATH--screen noneScreen 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 documentationExchange 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
Testing
python -m pytest tools/options-gps/tests/ -v→ 211 passed (119 existing + 92 new)Test breakdown
test_executor.py— 83 tests, 591 lines, 14 classes:TestInstrumentNamesTestBuildPlanTestValidatePlanTestDryRunExecutorTestExecuteFlowTestGetExecutorTestSlippageTestExecutionLogTestRetryableTestMonitoringAndCancelTestExecutionSavingsTestAevoSigningTestDeribitPriceConversionTestCLI--screen none/0/all,_refuse_executionblocks/allowstest_executor_e2e.py— 9 tests, 269 lines:--force, allows dry-run, allows when no guardrailEdge Cases Handled
get_executorraises with clear env var message--force; dry-run always allowedDiff vs existing codebase
executor.pymain.pytests/test_executor.pytests/test_executor_e2e.pyREADME.mdNot modified:
pipeline.py,exchange.py,requirements.txtEnvironment Variables (live execution only)
DERIBIT_CLIENT_ID/DERIBIT_CLIENT_SECRETDERIBIT_TESTNET=1AEVO_API_KEY/AEVO_API_SECRETAEVO_TESTNET=1None needed for
--dry-run.CLI Output:
--symbol BTC --view bullish --risk medium --dry-runScreen 5: Execution (dry-run)
Full 5-screen output
Demo Video
Coming soon
Checklist