For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See:

Sizer for CryptoCurrencies

  • Hi all,

    I'm currently deciding which backtester to use for testing stragies on trading cryptocurrencies.
    So far, I like backtrader a lot, but I still got one question.

    One of the characteristics of cryptocurrencies is, that one can buy only a fraction of a coin. With a relatively low capital,
    buying partial coins is very interesting.

    How can i accomplish that with backtrader? Do I have to write a sizer for this or does one already exist?


  • backtrader uses native floating point. Theoretically you should have no problem, but reality dictates otherwise, because cryptocurrencies tend to have a large amount of digits behind the dot and the actual representation is not exact. There is plenty of literature on that for any programming language, operating system and processor architecture.

    But if the amount of decimals is known and fixed in advance, 6 for example, you can actually work by moving the dot 6 places to right until you only have an integer.

    The results would need the opposite operation, but this would allow you to work without losing precision.

  • The default FixedSizer only support int type. You can implement your own fractional sizing.

  • Any pointers for getting there?

  • You don't mention whether you're using backtrader to do real trading and want to round per exchange / currency rules, or just have more accurate simulations.

    I actually wasn't able to get this to work in backtrader either, but honestly didn't try a whole lot on the simulation side. Rounding to 0.1 vs 1 if you're using simulated cash anyway isn't super meaningful. As Paska mentions, shifting up and down orders of magnitude could work but difficult (in my case, I simulated this by just increasing my starting cash by an order of magnitude instead -- e.g. if I'm trading LTC in increments of 0.1, I multiply my starting cash by 10 and divide the size of each trade by 10).

    In my case, I am using backtrader to generate signals to automatically trade. At the time I generate the orders for the exchanges, I perform exchange / currency-appropriate rounding of the approximated orders generated from backtrader. For me, I'm allocating a percentage of my capital in the account for each trade, and then sizing the order based on current bid/ask prices. Since a lot of this is dynamic based on what is actually on the order book, spending a lot of time getting backtrader to exactly size the order seemed not really to be worth the effort in my case.

    Not sure if this helps but thought I'd offer a suggestion.

  • @steven-vo I'm afraid that FixedSizer is not the problem. Order's attribute Size was defined as int. There is any way to sort this out? Thanks!

  • Maybe this will help someone... I had the same issue and solved it by using a percentage of my portfolio

    class Antoine_sizer(bt.Sizer):
        params = (('prop', 0.1),)
    def _getsizing(self, comminfo, cash, data, isbuy):
        """Returns the proper sizing"""
        if isbuy:    # Buying
            target = * self.params.prop    # Ideal total value of the position
            price = data.close[0]
            size_net = target / price    # How many shares are needed to get target
            size = size_net * 0.99
            if size * price > cash:
                return 0    # Not enough money for this trade
                return size
        else:    # Selling
            return    # Clear the position

Log in to reply