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

order_target_percent is not working as expected. Please read further; complete code, inputs and outputs are provided

  • Hi,

    I am running the Longshort strategy (provided as an example here: on BTC USD data (using fractional sizing as explained here:

    I'm using order_target_percent(0.5) in my code. I expect that for each buy operation, 50.0% of my cash should get used up. This does happen most of the time. Except when there is a buy immediately after a sell. The amount of cash that is used to make such buy operations is around 50%, but not exactly 50%.

    Check the buy operations on Row Id = 20 and Row Id = 46 in the linked output to see what I'm talking about. For ex, in row 20: I expect my cash value to go from 9908.73 to 4954.36 (which is 50%). Instead it goes from 9908.73 to 4947.38 (which is 49.92%). Buy operations on row 72 and 91 don't have this discrepancy.

    I suspect this could be due to rounding, but not sure. Let me know if any more info is required.

    Input data:


    from __future__ import (absolute_import, division, print_function,
    import pandas as pd
    import numpy as np
    import datetime
    import os
    import seaborn as sns
    import sys
    import copy
    import argparse
    import logging
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import backtrader.indicators as btind
    from backtrader.analyzers import SQN
    class CommInfoFractional(bt.CommissionInfo):
        def getsize(self, price, cash):
            '''Returns fractional size for cash operation @price'''
            return self.p.leverage * (cash / price)
    class act_buy_sell(
    	' For actual buy and sell prices'
        alias = ('Act_buy_sell',)
        lines = ('act_buy', 'act_sell', 'order_size')
        plotinfo = dict(plot=False, subplot=False)
        def next(self):
            for order in self._owner._orderspending:
                if is not
                if order.isbuy():
                    self.lines.act_buy[0] = order.executed.price
                    self.lines.order_size[0] = order.executed.size
                elif order.issell():
                    self.lines.act_sell[0] = order.executed.price
                    self.lines.order_size[0] = order.executed.size          
    class LongShortStrategy(bt.Strategy):
        '''This strategy buys/sells upong the close price crossing
        upwards/downwards a Simple Moving Average.
        It can be a long-only strategy by setting the param "onlylong" to True
        params = dict(
        def start(self):
        def stop(self):
        def log(self, txt, dt=None):
            if self.p.printout:
                dt = dt or[0]
                dt = bt.num2date(dt)
                print('%s, %s' % (dt.isoformat(), txt))
        def __init__(self):
            # To control operation entries
            self.orderid = None
            # Create SMA on 2nd data
            sma = btind.MovAv.SMA(, period=self.p.period)
            # Create a CrossOver Signal from close an moving average
            self.signal = btind.CrossOver(, sma)
            self.signal.csv = self.p.csvcross
        def next(self):
            if self.orderid:
                return  # if an order is active, no new orders are allowed
            if self.signal > 0.0:  # cross upwards
                if self.position:
                    self.log('CLOSE SHORT , %.2f' %[0])
                self.log('BUY CREATE , %.2f' %[0])
            elif self.signal < 0.0:
                if self.position:
                    self.log('CLOSE LONG , %.2f' %[0])
                if not self.p.onlylong:
                    self.log('SELL CREATE , %.2f' %[0])
        def notify_order(self, order):
            if order.status in [bt.Order.Submitted, bt.Order.Accepted]:
                return  # Await further notifications
            if order.status == order.Completed:
                if order.isbuy():
                    buytxt = 'BUY COMPLETE, %.2f' % order.executed.price
                    self.log(buytxt, order.executed.dt)
                    selltxt = 'SELL COMPLETE, %.2f' % order.executed.price
                    self.log(selltxt, order.executed.dt)
            elif order.status in [order.Expired, order.Canceled, order.Margin]:
                self.log('%s ,' % order.Status[order.status])
                pass  # Simply log
            # Allow new orders
            self.orderid = None
        def notify_trade(self, trade):
            if trade.isclosed:
                self.log('TRADE PROFIT, GROSS %.2f, NET %.2f' %
                         (trade.pnl, trade.pnlcomm))
            elif trade.justopened:
                self.log('TRADE OPENED, SIZE %2d' % trade.size)
    def runstrategy(period = 15
                    ,onlylong = True
                    ,csvcross = True
                    ,stake = 1
                    ,comm = 0
                    ,plot = True
                    ,fractional = True):
        # Create a cerebro
        cerebro = bt.Cerebro()
        # Create the 1st data
        data = btfeeds.GenericCSVData(
        dataname=data #refer to attached data
        fromdate=datetime.datetime(2017, 1, 1),
        todate=datetime.datetime(2017, 4, 9),
        # Add the 1st data to cerebro
        if fractional:
            # Add the commission - only stocks like a for each operation
        # Add the strategy
        # Add the commission - only stocks like a for each operation
        # cerebro.addanalyzer(SQN)
        cerebro.addwriter(bt.WriterFile, csv=True, rounding=2)
        # And run it
        # Plot if requested
        if plot:
            cerebro.plot(volume=True, zdown=False)
    runstrategy(plot = False, stake = 0.5)

  • @backtrader @ab_trader @run-out please have a look when you get the chance as this could potentially be a bug. Thanks!

Log in to reply