Skip to content

Advanced Strategies

This page explains some advanced concepts available for strategies. If you're just getting started, please be familiar with the methods described in the Strategy Customization documentation first.

Custom order timeout rules

Simple, timebased order-timeouts can be configured either via strategy or in the configuration in the unfilledtimeout section.

However, freqtrade also offers a custom callback for both ordertypes, which allows you to decide based on custom criteria if a order did time out or not.

Note

Unfilled order timeouts are not relevant during backtesting or hyperopt, and are only relevant during real (live) trading. Therefore these methods are only called in these circumstances.

Custom order timeout example

A simple example, which applies different unfilled-timeouts depending on the price of the asset can be seen below. It applies a tight timeout for higher priced assets, while allowing more time to fill on cheap coins.

The function must return either True (cancel order) or False (keep order alive).

from datetime import datetime, timestamp
from freqtrade.persistence import Trade

class Awesomestrategy(IStrategy):

    # ... populate_* methods

    # Set unfilledtimeout to 25 hours, since our maximum timeout from below is 24 hours.
    unfilledtimeout = {
        'buy': 60 * 25,
        'sell': 60 * 25
    }

    def check_buy_timeout(self, pair: str, trade: 'Trade', order: dict, **kwargs) -> bool:
        if trade.open_rate > 100 and trade.open_date < datetime.utcnow() - timedelta(minutes=5):
            return True
        elif trade.open_rate > 10 and trade.open_date < datetime.utcnow() - timedelta(minutes=3):
            return True
        elif trade.open_rate < 1 and trade.open_date < datetime.utcnow() - timedelta(hours=24):
           return True
        return False


    def check_sell_timeout(self, pair: str, trade: 'Trade', order: dict, **kwargs) -> bool:
        if trade.open_rate > 100 and trade.open_date < datetime.utcnow() - timedelta(minutes=5):
            return True
        elif trade.open_rate > 10 and trade.open_date < datetime.utcnow() - timedelta(minutes=3):
            return True
        elif trade.open_rate < 1 and trade.open_date < datetime.utcnow() - timedelta(hours=24):
           return True
        return False

Note

For the above example, unfilledtimeout must be set to something bigger than 24h, otherwise that type of timeout will apply first.

Custom order timeout example (using additional data)

from datetime import datetime, timestamp
from freqtrade.persistence import Trade

class Awesomestrategy(IStrategy):

    # ... populate_* methods

    # Set unfilledtimeout to 25 hours, since our maximum timeout from below is 24 hours.
    unfilledtimeout = {
        'buy': 60 * 25,
        'sell': 60 * 25
    }

    def check_buy_timeout(self, pair: str, trade: Trade, order: dict, **kwargs) -> bool:
        ob = self.dp.orderbook(pair, 1)
        current_price = ob['bids'][0][0]
        # Cancel buy order if price is more than 2% above the order.
        if current_price > order['price'] * 1.02:
            return True
        return False


    def check_sell_timeout(self, pair: str, trade: Trade, order: dict, **kwargs) -> bool:
        ob = self.dp.orderbook(pair, 1)
        current_price = ob['asks'][0][0]
        # Cancel sell order if price is more than 2% below the order.
        if current_price < order['price'] * 0.98:
            return True
        return False