Skip to content
All library documents

Tick-Triggered E-Mini Example with Bracket Orders and Position Exits

Code QTPyLib

Summary

This QTPyLib example illustrates a simple event-driven futures strategy for the S&P E-mini. It counts incoming ticks and acts on every tenth tick. When flat and without a pending order, it randomly chooses a side and submits a one-contract limit order around the latest price, with a target and initial stop placed a fixed distance away. The order also receives a tick-based expiry; if a position remains open at a later trigger, the strategy exits it.

The example demonstrates event callbacks, position and pending-order checks, tick and bar retrieval, order submission, and recording an action. It does not define a market signal: direction is random, and the stated target and stop are illustrative parameters. No backtest or profitability evidence is included, and the sample does not discuss fees, slippage, or risk sizing beyond its fixed contract quantity.

Key ideas

  • The strategy checks its state and considers action once every tenth tick.
  • When flat with no pending order, it randomly selects a buy or sell direction.
  • It submits a limit entry with a target, initial stop, and tick-based expiry.
  • An open position is exited at a later qualifying tick, while bars are only printed.
  • The code demonstrates order handling rather than a tested predictive trading signal.

Tags

Full text
# strategy.py


```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# QTPyLib: Quantitative Trading Python Library
# https://github.com/ranaroussi/qtpylib
#
# Copyright 2016-2018 Ran Aroussi
#
# 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.

import random

from qtpylib.algo import Algo
from qtpylib import futures


class TestStrategy(Algo):
    """
    Example: This Strategy buys/sells single contract of the
    S&P E-mini Futures (ES) every 10th tick with a +/- 0.5
    tick target/stop using LIMIT order.

    If still in position for next 5 ticks, an exit order is issued.
    """

    count = 0

    # ---------------------------------------
    def on_start(self):
        """ initilize tick counter """
        self.count = 0

    # ---------------------------------------
    def on_quote(self, instrument):
        # quote = instrument.get_quote()
        # ^^ quote data available via get_quote()
        pass

    # ---------------------------------------
    def on_orderbook(self, instrument):
        pass

    # ---------------------------------------
    def on_fill(self, instrument, order):
        pass

    # ---------------------------------------
    def on_tick(self, instrument):

        # increase counter and do nothing if nor 10th tick
        self.count += 1

        if self.count % 10 != 0:
            return

        # continue ...

        # get last tick dict
        tick = instrument.get_ticks(lookback=1, as_dict=True)

        if instrument.positions['position']:
            print(instrument.symbol, "still in position. Exiting...")
            instrument.exit()
        else:
            if instrument.pending_orders:
                print(instrument.symbol, "has a pending order. Wait...")
            else:
                # random order direction
                direction = random.choice(["BUY", "SELL"])
                print(instrument.symbol,
                      'not in position. Sending a bracket ', direction, 'order...')

                if direction == "BUY":
                    target = tick['last'] + 0.5
                    stoploss = tick['last'] - 0.5
                else:
                    target = tick['last'] - 0.5
                    stoploss = tick['last'] + 0.5

                instrument.order(direction, 1,
                                 limit_price=tick['last'],
                                 target=target,
                                 initial_stop=stoploss,
                                 trail_stop_at=0,
                                 trail_stop_by=0,
                                 expiry=5
                                 )

                # record action
                self.record(take_action=1)

    # ---------------------------------------
    def on_bar(self, instrument):
        # nothing exiting here...
        bar = instrument.get_bars(lookback=1, as_dict=True)
        print("BAR:", bar)



# ===========================================
if __name__ == "__main__":
    # get most active ES contract to trade
    ACTIVE_MONTH = futures.get_active_contract("ES")
    print("Active month for ES is:", ACTIVE_MONTH)

    strategy = TestStrategy(
        instruments=[("ES", "FUT", "GLOBEX", "USD", ACTIVE_MONTH, 0.0, "")],
        resolution="1T",
        tick_window=10,
        bar_window=10
    )
    strategy.run()

```

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.