Skip to main content

execution-model

Trade execution modeling (backtest only) — slippage formulas (linear / square-root impact), VWAP/TWAP execution logic, market-impact cost estimation, and execution-assumption configuration.

Quellinformationen

Repository
HKUDS/Vibe-Trading
Letzte Quellaktivität
5. August 2026 um 17:56
Erkannte Sprache von SKILL.md
Englisch
Sterne
34.287
Forks
5.577

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
execution-model
description
Trade execution modeling (backtest only) — slippage formulas (linear / square-root impact), VWAP/TWAP execution logic, market-impact cost estimation, and execution-assumption configuration.
category
strategy
# Trade Execution Modeling ## Overview Provide more realistic execution assumptions for backtests, including slippage models, market-impact estimation, and execution-algorithm principles. This skill is for backtest simulation only and does not involve live order execution. ## Slippage Models ### Why Slippage Models Are Needed ``` Idealized backtest: filled at the close, zero slippage Real world: 1. The order book has a bid-ask spread 2. Large orders push prices (market impact) 3. Execution is delayed (there is latency from signal to fill) No slippage model -> overly optimistic backtest -> losses in live trading ``` **Do not retype these models.** All four are implemented and tested in `src/quantlib/impact.py`; import them. The tested versions validate their inputs — a zero ADV raises instead of dividing by zero, and a negative `delay_bars` raises instead of silently introducing look-ahead bias. ```python from src.quantlib.impact import fixed_slippage, linear_impact, sqrt_impact, delayed_execution ``` ### 1. Fixed Slippage Model ```python fixed_slippage(price=100.0, direction=1, bps=5.0) # 100.05 (buy pays up) fixed_slippage(price=100.0, direction=-1, bps=5.0) # 99.95 (sell receives less) ``` `direction` is 1 to buy or -1 to sell, and must be exactly one of those — it multiplies the impact, so an unchecked 2 would silently double the modelled cost. `bps` defaults to `DEFAULT_SLIPPAGE_BPS` (5.0). **Reference fixed-slippage assumptions by market:** | Market | Instrument | Suggested Slippage (bps) | Notes | |------|------|-------------|------| | China A-share large cap | CSI 300 constituents | 3-5 | Good liquidity | | China A-share small cap | CSI 1000 constituents | 5-10 | Average liquidity | | China micro-cap | market cap < 5 billion RMB | 10-30 | Poor liquidity | | US large cap | AAPL / MSFT | 1-3 | Excellent liquidity | | Hong Kong stocks | Hang Seng constituents | 5-10 | Less liquid than A / US | | BTC spot | BTC-USDT | 2-5 | Good OKX liquidity | | ETH spot | ETH-USDT | 3-8 | Slightly worse than BTC | | Small altcoins | other `-USDT` pairs | 10-50 | Liquidity varies widely | ### 2. Linear Impact Model `impact = impact_coeff × volume_traded / adv` ```python # 100k shares against 1M ADV = 10% participation; at coeff 0.1 that is a 1% move. linear_impact(price=100.0, direction=1, volume_traded=100_000, adv=1_000_000, impact_coeff=0.1) # 101.0 ``` Marginal impact is constant here, which overstates the cost of very large orders. `impact_coeff` defaults to `DEFAULT_LINEAR_IMPACT_COEFF` (0.1). **Reference impact coefficients:** | Market | impact_coeff | Notes | |------|-------------|------| | China A-share large cap | 0.05-0.10 | 10% daily price-limit system | | China A-share small cap | 0.10-0.20 | Liquidity premium | | US equities | 0.03-0.08 | Market-maker buffering | | Crypto | 0.05-0.15 | 24h trading is dispersed | ### 3. Square-Root Impact Model `impact = η × σ × sqrt(volume_traded / adv)` ```python # 250k against 1M ADV = 25% participation; 0.5 × 0.02 × sqrt(0.25) = 0.005 = 50bps. sqrt_impact(price=100.0, direction=1, volume_traded=250_000, adv=1_000_000, volatility=0.02, eta=0.5) # 100.5 (100.49999999999999 in binary floating point) ``` `volatility` is daily return volatility as a decimal fraction. `eta` defaults to `DEFAULT_SQRT_IMPACT_ETA` (0.5); 0.3-0.8 is the usual calibrated range. **Advantages of the square-root model**: - Strongest empirical support (standard in financial literature) - Marginal impact declines for larger orders (intuitive) - Parameters can be estimated from historical data > **Naming.** This impact term is often labelled "Almgren-Chriss", and it does come > from that literature, but it is **not** Almgren-Chriss optimal execution. There is > no trading trajectory, no permanent/temporary impact split and no risk-aversion > parameter here, and none is implemented anywhere in this repository. Call it a > square-root impact function, and do not claim an optimal schedule was computed. ### Slippage Model Selection Decision Tree ``` Backtest capital vs instrument ADV: ├── Capital < 0.5% of ADV -> fixed slippage (5bps) is enough ├── Capital 0.5-5% -> linear impact model └── Capital > 5% -> square-root impact model (required) ``` ## Execution Algorithm Principles ### VWAP (Volume Weighted Average Price) ``` Goal: execute at the day's volume-weighted average price VWAP = Σ(Price_i × Volume_i) / Σ(Volume_i) Execution logic: 1. Forecast the intraday volume profile (typically U-shaped) 2. Split the order according to the predicted profile 3. Execute proportionally in each time slice Typical China A-share VWAP volume profile (U-shaped): 09:30-10:00 15% (active open) 10:00-11:30 25% (normal morning session) 13:00-14:00 15% (weak afternoon session) 14:00-14:30 15% (afternoon recovery) 14:30-15:00 30% (active close) VWAP in backtests: - Daily backtest: use the VWAP field directly as the fill price - Minute backtest: simulate VWAP order slicing ``` ### TWAP (Time Weighted Average Price) ``` Goal: execute evenly over a specified time window TWAP = simple time-sliced execution Execution logic: 1. Define an execution window (for example 09:30-11:30) 2. Divide it into N time buckets 3. Execute total_size / N in each bucket Pros and cons: + Simple, no need to forecast volume - Easier to cause impact during low-volume periods - Less adaptive than VWAP ``` ### Simulating Execution Delay in Backtests ```python signals = delayed_execution(raw_signal, delay_bars=1) # T+1: trade tomorrow on today's signal signals = delayed_execution(raw_signal, delay_bars=0) # same-bar execution ``` - China A-shares: `delay_bars=1` (T+1 rule) - Crypto: `delay_bars=0` or `1` A negative `delay_bars` raises. It would pull future signal values into the past, which is look-ahead bias and silently inflates every backtest containing it — the tested implementation refuses rather than letting that pass unnoticed. ## Integrated Transaction-Cost Model ### Total Cost Breakdown ``` Total trading cost = explicit cost + implicit cost Explicit cost: - Commission: China A-shares 2-3 bps, crypto 0.02-0.1% - Stamp duty (China A-share sell side): 0.05% (sell orders only) - Transfer fee: negligible Implicit cost: - Bid-ask spread: 0.5-5bps - Market impact: depends on trade size and liquidity - Opportunity cost: loss from not filling at the best price ``` ### Reference Trading Costs by Market | Cost Item | China A-shares | Hong Kong | US | Crypto (OKX) | |--------|-----|------|------|-----------| | Commission (one way) | 0.025% | 0.05% | 0 (zero commission) | 0.08% (maker) | | Stamp duty | 0.05% (sell) | 0.1% (both sides) | 0 | 0 | | Bid-ask spread | 0.03-0.1% | 0.05-0.2% | 0.01-0.05% | 0.01-0.05% | | Total one-way | ~0.1% | ~0.2% | ~0.03% | ~0.1% | | Total round-trip | ~0.2% | ~0.4% | ~0.06% | ~0.2% | ### Cost Settings in Backtests ```json { "commission": 0.001, "comment": "0.1% one-way commission, already includes stamp duty and spread" } ``` **Recommendations**: - China A-shares: `commission = 0.001` (conservative, includes all costs) - Crypto: `commission = 0.001` (including slippage) - Hong Kong / US equities: `commission = 0.001-0.002` ## Backtest Execution Assumptions ### Relevant `config.json` Settings ```json { "commission": 0.001, "engine": "daily", "interval": "1D" } ``` ### Advanced Execution Assumptions (implemented in `signal_engine.py`) ```python from src.quantlib.impact import delayed_execution class SignalEngine: def __init__(self): # Execution assumption parameters self.execution_delay = 1 # T+1 delay self.slippage_bps = 5 # Fixed 5bps slippage self.max_participation = 0.05 # Maximum participation rate 5% def generate(self, data_map): for code, df in data_map.items(): # 1. Generate raw signal raw_signal = self._compute_signal(df) # 2. Apply execution delay delayed_signal = delayed_execution(raw_signal, self.execution_delay) # 3. Apply volume filter (do not trade when liquidity is too low) volume_ok = df['volume'] > df['volume'].rolling(20).mean() * 0.3 delayed_signal[~volume_ok] = 0 signals[code] = delayed_signal ``` ## Analysis Framework ### Evaluate the Impact of Transaction Costs ``` Step 1: Estimate annual turnover Annual turnover = annual trade count × 2 (buy + sell) / number of positions Step 2: Compute annual cost drag Annual cost = annual turnover × total one-way cost Step 3: Evaluate the impact on returns Net return = gross return - annual cost Example: Annual turnover = 12 (monthly rebalance) One-way cost = 0.1% Annual cost = 12 × 0.1% = 1.2% If annualized return is only 5% -> costs eat 24% of returns! ``` ### Sensitivity Analysis for Execution Assumptions ```markdown ### Backtest Results Under Different Slippage Assumptions | Slippage (bps) | Annual Return | Sharpe | Max Drawdown | |-----------|---------|--------|---------| | 0 (ideal) | 15.2% | 1.35 | -18.5% | | 3 | 13.8% | 1.22 | -19.0% | | 5 | 12.9% | 1.15 | -19.2% | | 10 | 11.1% | 0.98 | -19.8% | | 20 | 7.5% | 0.65 | -20.5% | Conclusion: the strategy still has meaningful profitability under 10bps slippage ``` ## Output Format ```markdown ## Execution Cost Analysis ### Strategy Trading Characteristics | Metric | Value | |------|-----| | Average annual trade count | 48 | | Annual turnover | 4.8x | | Average holding days | 25 | | Average order size | ¥50,000 | ### Cost Estimate | Cost Item | Per Trade | Annualized | |--------|------|------| | Commission | 0.025% | 0.24% | | Stamp duty | 0.025% | 0.12% | | Estimated slippage | 0.03% | 0.29% | | **Total** | **0.08%** | **0.65%** | ### Cost Impact - Gross return: 12.5% - Net return: 11.85% - Cost drag: -0.65% (5.2% of gross return) - Conclusion: cost impact is manageable ### Optimization Suggestions 1. Lower turnover (lengthen holding period) 2. Avoid trading during low-liquidity windows 3. Use limit orders instead of market orders ``` ## Notes 1. **Backtest only**: this system does not execute live trades; the execution model is used only to improve backtest realism 2. **Conservative assumptions**: in backtests, it is better to overestimate transaction costs than to underestimate them 3. **China A-share T+1 rule**: trades cannot be executed on the same day the signal is generated, so execution must be delayed by 1 day 4. **Price-limit constraints**: when China A-shares are locked at limit-up / limit-down, no fill is possible; those dates should be skipped in backtests 5. **Volume constraints**: order size should not exceed 5-10% of the day’s traded volume, otherwise the impact model becomes invalid 6. **Backtest overfitting**: even with slippage included, the strategy may still overfit; out-of-sample validation matters more 7. **`commission` in config**: the default `0.001` (0.1%) is a reasonable all-in cost estimate 8. **The models are implemented, not improvised**: `src/quantlib/impact.py` holds all four, tested. Import them rather than retyping; the tested versions reject a zero ADV, a negative order size and a negative execution delay, all of which the retyped versions used to accept silently
Auf GitHub ansehen