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

Target order doesn't allow for fractions



  • Hi everybody,

    I'm new to backtrader and have been trying to code a long/short strategy to trade Bitcoin.
    After having some issues getting the strategy to use 100% of my capital and successfully reverse positions, I figured out that target orders are probably the easiest way to achieve that behaviour.
    My problem now is that it only seems to be possible to create orders for at least one full bitcoin and not fractions of it. Is there a way to change that?

    Also if I take commissions into account I can't set

    order_target_percent(target=1)
    

    or my orders would fail, correct?

    Thanks a lot for your help!


  • administrators

    @Robin-B said in Target order doesn't allow for fractions:

    After having some issues getting the strategy to use 100% of my capital

    Reality is hard ... price gaps ... commissions. Believe me when I say: "All-in is NOT the new black". And Mr. Martingale, a very close relative, is also not the new black. They are both old worn and wasted blacks.

    @Robin-B said in Target order doesn't allow for fractions:

    I figured out that target orders are probably the easiest way to achieve that behaviour.

    No it's not. It cannot be achieved, neither with backtrader nor in the market. And if backtrader gave it to you, it would be deceiving you.

    @Robin-B said in Target order doesn't allow for fractions:

    My problem now is that it only seems to be possible to create orders for at least one full bitcoin and not fractions of it. Is there a way to change that?

    I don't know nor does anyone else reading this thread. We don't know what you did and why you conclude that you can only buy one full bitcoin.

    @Robin-B said in Target order doesn't allow for fractions:

    order_target_percent(target=1)
    

    But as pointed out above, price gaps and commissions play a role. Don't use it, because it' something real.



  • Thanks for your quick answer!

    @backtrader said in Target order doesn't allow for fractions:

    No it's not. It cannot be achieved, neither with backtrader nor in the market. And if backtrader gave it to you, it would be deceiving you.

    ok, I won't try to achieve it, for now my main goal is to replicate the backtesting results I got in Tradingview.

    @backtrader said in Target order doesn't allow for fractions:

    I don't know nor does anyone else reading this thread. We don't know what you did and why you conclude that you can only buy one full bitcoin.

    Here is my strategy:

    import backtrader as bt
    import backtrader.analyzers as btanalyzers
    import backtrader.feeds as btfeed
    from datetime import datetime
    import math
    
    
    class MAcross(bt.Strategy):
    
        params = (
            ("debug", False),
            ('smafast', 20),
            ('smaslow', 80),
        )
    
        def __init__(self):
            self.smafast = bt.indicators.MovingAverageSimple(period=self.p.smafast)
            self.smaslow = bt.indicators.MovingAverageSimple(period=self.p.smaslow)
            self.crossup = bt.indicators.CrossUp(self.smafast, self.smaslow)
            self.crossdown = bt.indicators.CrossDown(self.smafast, self.smaslow)
    
            self.buy_sig = self.crossup
            self.sell_sig = self.crossdown*-1
    
        def next(self):
    
            if not self.position:
    
                if self.sell_sig:
    
                    self.order_target_percent(target=-0.5)
                    print('sell')
    
                if self.buy_sig:
                    self.order_target_percent(target=0.5)
                    print('buy')
    
            else:
                if self.position.size > 0:
                    if self.sell_sig:
                        print('reverse to short')
                        self.order_target_percent(target=-0.5)
    
    
                else:
                    if self.buy_sig:
                        print('reverse to long')
                        self.order_target_percent(target=0.5)
    
    
            if self.p.debug:
                print('---------------------------- NEXT ----------------------------------')
                print("1: Data Name:                            {}".format(data._name))
                print("2: Bar Num:                              {}".format(len(data)))
                print("3: Current date:                         {}".format(data.datetime.datetime()))
                print('4: Open:                                 {}'.format(data.open[0]))
                print('5: High:                                 {}'.format(data.high[0]))
                print('6: Low:                                  {}'.format(data.low[0]))
                print('7: Close:                                {}'.format(data.close[0]))
                print('8: Volume:                               {}'.format(data.volume[0]))
                print('9: Position Size:                        {}'.format(self.position.size))
                print('--------------------------------------------------------------------')
    
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = dt or self.data.datetime[0]
            if isinstance(dt, float):
                dt = bt.num2date(dt)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                self.log('ORDER ACCEPTED/SUBMITTED', dt=order.created.dt)
                self.order = order
                return
    
            if order.status in [order.Expired]:
                self.log('BUY EXPIRED')
    
            elif order.status in [order.Completed]:
                if order.isbuy():
                    self.log(
                        'BUY EXECUTED, Size: %.4f Price: %.2f, Cost: %.2f, Comm %.2f' %
                        (order.executed.size,
                         order.executed.price,
                         order.executed.value,
                         order.executed.comm))
    
                else:  # Sell
                    self.log('SELL EXECUTED, Size: %.4f Price: %.2f, Cost: %.2f, Comm %.2f' %
                             (order.executed.size,
                              order.executed.price,
                              order.executed.value,
                              order.executed.comm))
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected')
    
            # Sentinel to None: new orders allowed
            self.order = None
    
        def notify_trade(self,trade):
            if trade.isclosed:
                dt = self.data.datetime.date()
    
                print('---------------------------- TRADE ---------------------------------')
                #print("1: Data Name:                            {}".format(trade.data._name))
                #print("2: Bar Num:                              {}".format(len(trade.data)))
                print("3: Current date:                         {}".format(dt))
                print('4: Status:                               Trade Complete')
                print('5: Ref:                                  {}'.format(trade.ref))
                print('6: PnL:                                  {}'.format(round(trade.pnl,2)))
                print('6: PnL comm:                                {}'.format(round(trade.pnlcomm,2)))
                print('7: Account Value:                        {}'.format(round(self.broker.getvalue(),2)))
                print('7: Cash:                                 {}'.format(round(self.broker.getcash(),2)))
                print('--------------------------------------------------------------------')
    
    
    # Create an instance of cerebro
    cerebro = bt.Cerebro()
    
    #Variable for our starting cash
    startcash = 100000
    cerebro.broker.setcash(startcash)
    
     # Set the commission
    cerebro.broker.setcommission(commission=0.001)
    
    # Add our strategy
    cerebro.addstrategy(MAcross)
    
    class customCSV(btfeed.GenericCSVData):
            params = (
            ('dtformat', '%Y-%m-%dT%H:%M:%S.%fZ'),
            ('datetime', 0),
            ('open', 1),
            ('high', 2),
            ('low', 3),
            ('close', 4),
            ('volume', 5),
            ('openinterest', -1)
            )
    
    
    data = customCSV(dataname='data/binance-BTCUSDT-1d_tv.csv')
    
    # Add the data to Cerebro
    cerebro.adddata(data)
    
    # Run over everything
    thestrats = cerebro.run()
    thestrat = thestrats[0]
    
    #Get final portfolio Value
    portvalue = cerebro.broker.getvalue()
    pnl = portvalue - startcash
    
    #Print out the final result
    
    print('Final Portfolio Value: ${}'.format(round(portvalue,2)))
    print('P/L: ${}'.format(round(pnl,2)))
    print('P/L: {}%'.format(round(pnl/startcash*100,2)))
    
    # Finally plot the end results
    cerebro.plot(style='candlestick')
    

    The first output is the following:

    sell
    2018-01-27T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
    2018-01-27T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
    2018-01-28T23:59:59.999989, SELL EXECUTED, Size: -4.0000 Price: 11499.98, Cost: -45999.92, Comm 46.00
    

    Using half of my $100k to buy BTC at a price of $11499.98, I should be able to buy ~4.34 BTC but the order is only for 4 BTC.


  • administrators


Log in to reply
 

});