Volume-Share Slippage Modeling in a Dollar-Neutral Stock Strategy
Summary
This example demonstrates applying a volume-share slippage model to a stock portfolio selected from an ETF’s constituents. The model is configured to limit fills to a fraction of historical trading volume and apply a specified market impact. The universe selection ranks constituents by weight, going long the most heavily weighted names and short the least weighted names. Holdings are assigned equal positive and negative portfolio weights, producing a dollar-neutral portfolio intended to reduce broad market exposure.
The example illustrates how execution assumptions can be integrated into a backtest and how a ranked long-short portfolio can be formed. It specifies daily resolution and a short sample period, but gives no return, risk, or slippage analysis, so it does not establish strategy performance. The selection rule is based on ETF constituent weights, which the code comments interpret as popularity; that interpretation is not validated in the example. Results would depend on universe membership, volume data, and the chosen impact and fill parameters.
Key ideas
- The example assigns a volume-share slippage model to securities through a security initializer.
- The model limits fills relative to historical volume and applies a market-impact assumption.
- The universe ranks ETF constituents by weight, buying the highest-ranked names and shorting the lowest-ranked names.
- Equal positive and negative weights are used to construct a dollar-neutral portfolio.
- The short example contains no reported performance or analysis validating its ranking rationale or execution assumptions.
Tags
Full text
# VolumeShareSlippageModelAlgorithm
# VolumeShareSlippageModelAlgorithm
Example algorithm implementing VolumeShareSlippageModel.
## Source (Apache-2.0)
```python
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
from Orders.Slippage.VolumeShareSlippageModel import VolumeShareSlippageModel
### <summary>
### Example algorithm implementing VolumeShareSlippageModel.
### </summary>
class VolumeShareSlippageModelAlgorithm(QCAlgorithm):
_longs = []
_shorts = []
def initialize(self) -> None:
self.set_start_date(2020, 11, 29)
self.set_end_date(2020, 12, 2)
# To set the slippage model to limit to fill only 30% volume of the historical volume, with 5% slippage impact.
self.set_security_initializer(lambda security: security.set_slippage_model(VolumeShareSlippageModel(0.3, 0.05)))
self.universe_settings.resolution = Resolution.DAILY
# Add universe to trade on the most and least weighted stocks among SPY constituents.
self.add_universe(self.universe.etf("SPY", universe_filter_func=self.selection))
def selection(self, constituents: list[ETFConstituentUniverse]) -> list[Symbol]:
sorted_by_weight = sorted(constituents, key=lambda c: c.weight)
# Add the 10 most weighted stocks to the universe to long later.
self._longs = [c.symbol for c in sorted_by_weight[-10:]]
# Add the 10 least weighted stocks to the universe to short later.
self._shorts = [c.symbol for c in sorted_by_weight[:10]]
return self._longs + self._shorts
def on_data(self, slice: Slice) -> None:
# Equally invest into the selected stocks to evenly dissipate capital risk.
# Dollar neutral of long and short stocks to eliminate systematic risk, only capitalize the popularity gap.
targets = [PortfolioTarget(symbol, 0.05) for symbol in self._longs]
targets += [PortfolioTarget(symbol, -0.05) for symbol in self._shorts]
# Liquidate the ones not being the most and least popularity stocks to release fund for higher expected return trades.
self.set_holdings(targets, liquidate_existing_holdings=True)
```Shown in full with attribution under the source's licence. Licence: Apache-2.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.