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

Sizer problem



  • So I tried using an example sizer from Backtest-Rookies and implemented it to my own code
    https://backtest-rookies.com/2017/07/24/developing-sizers-backtrader-part-1/


    #This is the example code that they provided:

    class MaxRiskSizer(bt.Sizer):
        '''
        Returns the number of shares rounded down that can be purchased for the
        max rish tolerance
        '''
        params = (('risk', 0.03),)
    
        def __init__(self):
            if self.p.risk > 1 or self.p.risk < 0:
                raise ValueError('The risk parameter is a percentage which must be'
                    'entered as a float. e.g. 0.5')
    
        def _getsizing(self, comminfo, cash, data, isbuy):
            if isbuy:
                size = math.floor((cash * self.p.risk) / data[0])
            else:
                size = math.floor((cash * self.p.risk) / data[0]) * -1
            return size
    
    cerebro.addsizer(MaxRiskSizer, risk=0.5)
    
    

    ...............................................................................................................................................................
    I set the risk at (risk = 0.5) , so it should mean I am going to use 50% of the portfolio to enter a trade right?

    #This is my code(I seperated the stategy class and main):

    1. Main:
    import backtrader as bt
    import datetime
    import math
    from Strategy import TestStrategy
    
    cerebro = bt.Cerebro()
    cerebro.broker.set_cash(100000)
    cerebro.broker.setcommission(0.01)
    data = bt.feeds.YahooFinanceCSVData(
        dataname="oracle.csv",
        fromdate=datetime.datetime(2000,3,1),
        todate=datetime.datetime(2000,4,29),
        reverse=False)
    class MaxRiskSizer(bt.Sizer):
        '''
        Returns the number of shares rounded down that can be purchased for the
        max rish tolerance
        '''
        params = (('risk', 0.03),)
    
        def __init__(self):
            if self.p.risk > 1 or self.p.risk < 0:
                raise ValueError('The risk parameter is a percentage which must be'
                    'entered as a float. e.g. 0.5')
    
        def _getsizing(self, comminfo, cash, data, isbuy):
            if isbuy:
                size = math.floor((cash * self.p.risk) / data[0])
            else:
                size = math.floor((cash * self.p.risk) / data[0]) * -1
            return size
    
    cerebro.adddata(data)                   #Insert Data.
    cerebro.addstrategy(TestStrategy)
    #cerebro.addsizer(bt.sizers.FixedSize, stake=2)
    cerebro.addsizer(MaxRiskSizer, risk=0.5)
    
    
    print("Starting Portfolio :%.2f" % cerebro.broker.getvalue())
    print()
    cerebro.run()
    print("Final Portfolio Value:%.2f" % cerebro.broker.getvalue())
    cerebro.plot(style="candlestick",barup='green', bardown='red')
    
    1. Strategy class :
    import backtrader as bt
    
    class TestStrategy(bt.Strategy):
    
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            self.dataclose = self.datas[0].close
            # To keep track of pending orders and buy price/commission
            self.order = None
            self.buyprice = None
            self.buycomm = None
    
        def notify_order(self,order):
            if order.status in [order.Submitted, order.Accepted]:
                return
    
            # Check if an order has been completed. Broker could reject if not enough cash
            if order.status in[order.Completed]:
                if order.isbuy():
                    self.log("BUY EXECUTED,Price: %.2f, Cost: %.2f, Comm %.2f" %
                             (order.executed.price,
                              order.executed.value,
                              order.executed.comm))
    
                    self.buyprice = order.executed.price
                    self.buycomm = order.executed.comm
    
                elif order.issell():
                    self.log("SELL EXECUTED,Price: %.2f, Cost: %.2f, Comm %.2f" %
                             (order.executed.price,
                              order.executed.value,
                              order.executed.comm))
    
                self.bar_executed = len(self)
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log("Order Cancled/Margin/Rejected")
    
            self.order = None
    
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            self.log("OPERATION PROFIT, GROSS %.2f NET %.2f" %
                     (trade.pnl, trade.pnlcomm))
            print()
    
        def next(self):
            # Simply log the closing price of the series from the reference
            #self.log('Close, %.2f' % self.dataclose[0])
    
            if self.order:
                return
    
            #If we are not in the market, we might buy.
            if not self.position:
                if self.dataclose[0] < self.dataclose[-1]:
                    # current close less than previous close
    
                    if self.dataclose[-1] < self.dataclose[-2]:
                        # previous close less than the previous previous close
    
                        # BUY, BUY, BUY!!! (with all possible default parameters)
                        self.log('BUY CREATED, %.2f' % self.dataclose[0])
                        self.order = self.buy()
            else:
                if len(self) >= (self.bar_executed + 5):
                    self.log("SELL CREATED {}".format(self.dataclose[0]))
                    self.order = self.sell()
    
    

    ...............................................................................................................................................................
    Starting Portfolio :100000.00

    2000-03-02, BUY CREATED, 30.47
    2000-03-03, BUY EXECUTED,Price: 31.63, Cost: 51873.20, Comm 518.73
    2000-03-10, SELL CREATED 36.3
    2000-03-13, SELL EXECUTED,Price: 34.91, Cost: 20717.65, Comm 228.66
    2000-03-20, SELL CREATED 34.75
    2000-03-21, SELL EXECUTED,Price: 34.63, Cost: 30289.80, Comm 349.76
    2000-03-21, OPERATION PROFIT, GROSS 5103.40 NET 4014.90

    2000-03-28, SELL CREATED 38.5
    2000-03-29, SELL EXECUTED,Price: 38.28, Cost: -52099.08, Comm 520.99
    2000-04-05, SELL CREATED 34.8
    2000-04-06, SELL EXECUTED,Price: 35.86, Cost: -80577.42, Comm 805.77
    2000-04-13, SELL CREATED 31.99
    2000-04-14, SELL EXECUTED,Price: 31.10, Cost: -114821.20, Comm 1148.21
    2000-04-24, SELL CREATED 32.22
    2000-04-25, SELL EXECUTED,Price: 33.30, Cost: -180785.70, Comm 1807.86
    Final Portfolio Value:75467.86
    ...............................................................................................................................................................

    Problem is:

    1. Just on the first buy, my portfolio starts at $100k but it uses $51.8k instead of amount < $50k. (Note: risk is 0.5)

    2. Some of the costs are negative. :/

    so,
    how do I fix the negative, is there something I am missing out or don't understand?



  • @Edward-Owen said in Sizer problem:

    Just on the first buy, my portfolio starts at $100k but it uses $51.8k instead of amount < $50k. (Note: risk is 0.5)

    int(100,000$ x 0.5 / 30.47$ (close price)) * 31.63$ (execution price) = 51,873.2$



  • @Edward-Owen said in Sizer problem:

    Some of the costs are negative.

    cost = size x price
    size is negative for short position, therfore cost is also negative.



  • @ab_trader okay that makes sense



  • @ab_trader said in Sizer problem:

    @Edward-Owen said in Sizer problem:

    Some of the costs are negative.

    cost = size x price
    size is negative for short position, therfore cost is also negative.

    I am quite new to python and backtrader, can you point me out which code is shorting my trades, I thought that my code only goes long.



  • @Edward-Owen said in Sizer problem:

    can you point me out which code is shorting my trades,

                if len(self) >= (self.bar_executed + 5):
                    self.log("SELL CREATED {}".format(self.dataclose[0]))
                    self.order = self.sell()
    

    This is what you are doing in your code:

    • 03/03 bought 100,000$ x 0.5 / 30.47 = 1,640 shares, 47,608.07$ cash left, long 1640 shares
    • 03/13 sold 47,608.07$ x 0.5 / 36.3 = 655 shares, 70,245.46$ cash left, long 985 shares
    • 03/21 sold 70,245.64$ x 0.5 / 34.75 = 1,010 shares, closed long position and open short position for 1,010 - 985 = 25 shares
      starting from this time every 5 bars you will be adding to short position.


  • thankss!



  • So is this the code to short or exit a trade, im kind of confused.
    and sorry but what does len(self) mean?

            else:
                if len(self) >= (self.bar_executed + 5):
                    self.log("SELL CREATED %.2f" % self.dataclose[0])
                    self.order = self.sell()
    


  • @Gleetche said in Sizer problem:

    So is this the code to short or exit a trade, im kind of confused.

    this code sells shares/futures. it can (1) decrease existing long position, (2) close existing long position, (3) open new short position or (2) and (3) at the same time.

    and sorry but what does len(self) mean?

    Docs - Platform Concepts - Lines len



  • @ab_trader okay that clears it up


Log in to reply
 

});