Trade Executor
repository·master·Indexed 41 days ago
https://github.com/tradingstrategy-ai/trade-executorA Python framework for algorithmic trading backtesting and live execution in the DeFi ecosystem. It supports decentralized exchanges like Uniswap and PancakeSwap, featuring a Generic Router for automated liquidity protocol selection, a webhook web server for monitoring, and integration with Pyodide and CCXT.
What's inside Trade Executor
- Trade Executor is a Python framework designed for the backtesting and live execution of algorithmic trading strategies specifically on decentralized exchanges (DeFi). It supports decentralized markets like Uniswap and PancakeSwap and includes features for live trading, backtesting, and a webhook web server for integration with monitoring systems or JavaScript frontends.
Overview of the Lagoon Lighter Manual Trade Tutorial
masterThe
manual-trade-executor-lighter.pytutorial is a live Ethereum-mainnet Python script designed to exercise the complete single-owner Lagoon/Lighter lifecycle. It is intended for real-money manual testing of the integration between Lagoon vaults, Safe-owned Lighter accounts, and thetrade-executorengine.The lifecycle covered includes:
- Deployment: Deploying a Lagoon vault and activating its Safe-owned Lighter account via
lagoon-deploy-vault. - Initialization: Setting up
trade-executorstate and Lighter external exchange-account positions. - Funding: Subscribing USDC to Lagoon and depositing it from the Safe to Lighter.
- Trading: Opening and closing small ETH-USD perpetual positions using Lighter API keys.
- Withdrawal: Securely withdrawing USDC from Lighter back to the Lagoon Safe.
- Redemption: Redeeming all deployer-owned Lagoon shares to return assets to the deployer.
- Deployment: Deploying a Lagoon vault and activating its Safe-owned Lighter account via
Understand the Trade-executor Vault Test Fix Plan
masterThis document outlines the implementation plan to resolve issues identified during a 129-vault cross-chain simulation. The goal is to improve the reliability of vault simulations and diagnostics by correctly classifying failures (e.g., closed deposit windows, unsupported adapters, or capacity limits) rather than aiming for a 100% success rate.
Key objectives include:
- Executing synchronous vault flows via selected
eth-defideposit managers. - Settling asynchronous request trades without assuming standard ERC-4626 selectors.
- Classifying unsupported adapters and closed deposit windows before pricing.
- Bridging exact USDC proceeds from satellite vault redemptions.
- Preserving transaction-evidence precedence during failed operations.
- Executing synchronous vault flows via selected
Locate strategy executor state files
masterWhen running live strategy executors, the system writes state files to the directory defined by thestate/path. These files contain the persistent state required for the executor to maintain continuity across restarts or sessions.Understand cross-chain vault simulation results and status codes
masterWhen running the vault matrix, the executor categorizes vault lifecycles into several terminal and non-terminal statuses. Understanding these helps distinguish between protocol-level issues and executor-level configuration issues.
Success & Lifecycle States
- Success (simulated): Deposit and redemption lifecycle completed successfully.
- Deposit closed: The vault is currently on-chain but does not admit new deposits (e.g., Yearn
maxDeposit=0). - Whitelisting needed: The simulated executor Safe is not admitted to the vault.
Failure & Gap States
- Simulation unsupported async: The redemption is asynchronous, and no Anvil driver was available to handle the pending ticket.
- Transaction reverted: A home-chain or satellite redemption/deposit reverted on-chain.
- Execution failed: Typed failures related to capacity, minimums, or preflight checks (e.g.,
redemption shares below minimum). - Broadcast failed: Reverts occurring during the
settleDeposit()allowance phase (e.g., Lagoon). - Redemption unavailable: The protocol accepted the deposit but provides no redemption path (e.g., Plutus).
- Adapter unsupported: The vault requires a specific manager (e.g., Upshift) that the current preflight logic is not routing correctly.
Understand the Lighter NAV calculation and syncing
masterThe
trade-executorintegrates Lighter positions into the Lagoon NAV syncing process via theExchangeAccountSyncModelandLagoonVaultSyncModel.NAV Logic:
- The system uses the Lighter exchange-account adapter to fetch total equity via
fetch_lighter_total_equity(). - The valuation uses the total asset value (collateral + unrealised PnL) rather than just the collateral amount.
- Safe USDC is explicitly excluded from the exchange-account position to avoid double-counting.
- Error Handling: If the public API returns negative equity, the system aborts the valuation and ensures no Lagoon valuation transaction is broadcast.
- Syncing Workflow: The system reconciles the Lighter total asset value with the Safe's on-chain USDC balance to update the USD-denominated position and preserve valuation history.
- The system uses the Lighter exchange-account adapter to fetch total equity via
Understand the Lighter exchange account value and custody model
masterLighter integration follows an external exchange-account model where capital resides in a Safe-owned account on Lighter. The Safe remains the owner and uses a guarded module to deposit USDC to Lighter or claim withdrawals back to the Safe. Trading is performed using a delegated Lighter API key registered in a specific numbered key slot.
Valuation Logic
The strategy universe contains a synthetic Lighter exchange-account pair. Its value is derived from Lighter's public
total_asset_value(including collateral and unrealized PnL).The Lagoon NAV is calculated as:
Safe native-USDC balance+public Lighter total equity+pending Lagoon settlement valueHandle asynchronous vault settlement with manager-aware receipt selection
masterTo support asynchronous vault settlement without relying on a global fixed-selector list, the system uses transaction tagging and request ordinals.
Transaction Tagging
At construction, every signed transaction must be tagged with a durable role:
vault_approvalvault_request
Identity is maintained via the request ordinal and its position in the trade's transaction list. Do not use the transaction hash as the durable identity, as retry signing can change it. Instead, store the raw amount, owner, and direction required to reconstruct the
eth-defirequest.Settlement Workflow
When
vault_async_flowis detected before callingget_swap_transactions():- Select all transactions tagged
vault_request, ordered by their persisted request ordinal. - Verify every selected request transaction has a successful receipt.
- Pass the ordered hash list to
parse_deposit_transaction()orparse_redeem_transaction(). - Use the final request receipt for the lifecycle timestamp (unless the parsed ticket provides a more precise one).
Compatibility and Migration
- Use
get_swap_transactions()only for non-async swaps and synchronous compatibility. - To upgrade legacy pending async trades (which lack roles), use the existing
vault_request_tx_countto identify the final ordered request transactions, stamp the new roles, and persist the upgraded state before retrying. - New metadata should be stored in optional
other_datafields to avoid schema migrations.
Manage vault positions via CoW Swap
masterFor certain vaults (specifically Lagoon vaults with CoW Swap integration enabled via
TradingStrategyModuleV0), you can trade vault share tokens directly on the open market using CoW Swap. This bypasses the vault's internaldeposit()/redeem()mechanisms.When to use CoW Swap:
- The vault has a deposit queue or settlement delay (e.g., Lagoon vaults).
- You need to acquire or exit shares immediately without waiting for settlement.
- The vault share token has sufficient liquidity on DEXes (e.g., Uniswap, Balancer) that CoW Swap can route through.
Important Considerations:
- Liquidity: The share token must be traded on secondary markets.
- Price Slippage: The market price on DEXes may differ from the vault's NAV-based share price. Always verify the price before executing.
- Context: The
vaultobject in the console refers to the Lagoon vault owning the strategy, not the target vault being traded.
from tradeexecutor.ethereum.cowswap.swap_to_vault import ( open_vault_position_cowswap, close_vault_position_cowswap, ) # Open a new $100 position (or increase existing) open_vault_position_cowswap( locals(), vault_name="IPOR USDC Lending Optimizer", amount_usd=100.0, ) # Close the entire position close_vault_position_cowswap( locals(), vault_name="IPOR USDC Lending Optimizer", ) # Or reduce by selling a specific number of shares close_vault_position_cowswap( locals(), vault_name="IPOR USDC Lending Optimizer", shares_to_sell=50.0, )Understand the Async Vault Settlement Simulation Modes
masterWhen performing simulated redemption trials for vaults in
trade-executor, the system uses an ordered fallback state machine to test if a vault can settle. These modes are used to distinguish between a vault that is naturally liquid/open and one that requires simulation concessions (like injected liquidity or status overrides) to succeed in a fork environment.All three modes are considered valid success results for the matrix, but they must be recorded distinctly to ensure the report does not falsely imply a live vault was liquid or open.
The three simulation modes are:
simulated_ok: The vault settles and claims/payouts against an unmodified fork (strict mode).simulated_liquidity_added: Used when strict mode fails due to a lack of redemption liquidity. The system injects the required fork-only liquidity on Anvil and then settles/claims/payouts. The record must include the injected raw amount, the original balance, and the shortfall.simulated_bypass_closed_status: Used when the prior modes are blocked by a closed, paused, capped, or admission/whitelist status. The system uses an Anvil-only state or policy override to settle/claim/payout. The record must include the exact bypassed status and the original preflight evidence.
How automatic fork block resolution works
masterIf you do not provide the
--simulation-fork-blockflag, the executor uses Automatic mode.In this mode, the system:
- Identifies the most recent naive UTC midnight at command setup.
- Resolves the latest block number at or before that timestamp for every selected chain using
create_multi_provider_web3()and a timestamp binary search. - Fails setup if a selected chain cannot resolve or serve that historical block (it will not silently fall back to a live tip).
Provenance for these runs is recorded with
fork_block_sourceset toautomatic_midnightalong with the selected midnight timestamp.Understand the Vault Test Result Contract
masterWhen performing vault tests, the system produces specific outcome results. Developers should use these typed outcomes to classify trade attempts. Every typed outcome must include a concise
detailstring. For capacity-related results, you must also include anoutcome_datamapping containing the requested and available raw amounts in JSON-safe form to avoid requiring reporters to parse thedetailstring.New Outcomes
adapter_unsupported: Theeth-defisubmodule explicitly states the requested direction is not implemented.redemption_capacity_limited: The requested immediate redemption exceeds current protocol capacity.async_request_only: The configured simulation confirmed an async request without requesting its full lifecycle.
Existing Outcomes
deposit_closed: Known closed deposit window, paused deposit, or zero current deposit capacity.redemption_unavailable: Known closed redemption window.simulation_unsupported_async: A full async lifecycle was requested but no safe Anvil settlement driver is available.receipt_analysis_failed: A mined status-1 transaction exists, but the protocol adapter cannot produce a valid flow analysis.execution_failed: No more specific typed or evidence-based outcome applies.
{ "result": "redemption_capacity_limited", "detail": "Immediate redemption capacity is below the requested amount", "outcome_data": { "direction": "redeem", "requested_raw_amount": "907757", "available_raw_amount": "45388" } }