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

Custom Commission Scheme that take a timeseries for Interest



  • Dear All,

    Has anyone implemented implemented a custom Commission Scheme that takes a timeseries/feed as input instead of a flat fixed rate? If someone is kee to share; I'd like to take a look.

    Many thanks in advance
    Lamp'

    Re: Access get_credit_interest in next()



  • Could you provide an example please? Thanks.



  • Hi,

    Usually, brokers will charge interests when taking SHORT position on stocks. Backtrader allows you to define a fixed interest % for this using out of the box commission scheme (https://www.backtrader.com/docu/commission-credit/). However; I'd like to run backrests over a long period of time (various interest rate regime) and therefore I would like to be able to model this interest rate as Fed Fund rate + 50bp for instance. I can easily create a data feed for FF+50 bp. What I would like to know is if someone has already created a custom Commission Scheme that allows variable interest rate over time.

    Ideally, we would pass a datafeed to the Commission Scheme constructor (instead of fixed rate) and the method _get_credit_interest() would fetch the right prevailing interest rate.

    Hope this is clear enough.

    Kind regards,
    Lamp'



  • OK, that helps a lot.

    First thing is you need to add a signal to your data line, or independently as a separate line. I'm going to assume you know that part. If not, let us know. Let's assume you add a data line as FF to your data feed.

    Now you need to create a class for the commission. The _get_credit_interest method has the data line in it, so hopefully you aren't using the method. We can call the method internally and get return the data line. From there we isolate your FF line and get the current value.

    class CommissionFF(bt.CommInfoBase):
        """Custom commission for both trading and brokerage charges."""
    
        params = (
            ("commtype", bt.CommissionInfo.COMM_PERC),
            ("commission", 0.0004),
        )
    
        def _getcommission(self, size, price, pseudoexec):
            """Calculates the commission of an operation at a given price """
            
            return abs(size) * self.p.commission * data.FF[0]
    
        def _get_credit_interest(self, data, size, price, days, dt0, dt1):
    
            return data
    
    

    Of course you need to add all this in to cerebro. I've added in the kwargs as an example only.

     comm_kwargs = dict(
            commission=float(.0004),
        )
    
        comminfo = CommissionFF(**comm_kwargs)
    
        cerebro.broker.addcommissioninfo(comminfo)
    


  • @run-out said in Custom Commission Scheme that take a timeseries for Interest:

    e a class for the commission. The _get_credit_interest method has the data line in it, so hopefully you aren't using the method. We can call the method internally and get return the data line. From there we isolate your FF line and get the current value.

    I'll give it a try; I'll keep you posted. thanks a lot



  • I think I got lost in the question a bit. I just re-read the question, you can simply access the data line in the _get_credit_interest() method and modify your rate. Sadly I can't adjust my previous response.

    class CommissionFF(bt.CommInfoBase):
        """Custom commission """
    
        params = (
            ("commtype", bt.CommissionInfo.COMM_PERC),
            ("commission", 0.0004),
        )
    
        def _get_credit_interest(self, data, size, price, days, dt0, dt1):
    
            int_rate = data.FF[0] + 0.5
    
           return    calculations etc...
    


  • Hi @run-out

    Thanks a lot for your answer. I have started looking at this and unfortunately; I'm hitting a very strange issue.
    For now, I just want to create a custom Commission Scheme that applies interest on Short AND Long positions. The little twist is that I want to apply different interest rate for Short and for Long side. let say for argument sake 1.5% for Long position, 4.5% for Short side.

    I feel what I'm doing is fairly simple and should work but for some reasons, I get an error that says "TypeError: getvaluesize() missing 1 required positional argument: 'price'"

    I initially thought that my backtrader version was too out-dated; so I have updated it to 1.9.75.123).

    I looked at the code on github but I really don't understand why I get this error. Any help/insights would be greatly
    appreciated! Note that everything works blissfully if I remove this Commission Scheme.

    Kind regards
    Lamp'

    class CommissionFF(bt.CommInfoBase):
        params = (
            ("commtype", bt.CommissionInfo.COMM_PERC),
            ("commission", 0.0),
        )
    
        def _get_credit_interest(self, data, size, price, days, dt0, dt1):
            # days * abs(size) * price * (interest / 365)
            if size > 0: # Long
                return days * abs(size) * price * (0.015 / 265)
            else: # Short
                return days * abs(size) * price * (0.045 / 265)
    
    ----
    # Usage of the comminfo:
    
    # data from TS
    data0 = get_data_feed('tradestation', os.path.join(data_folder, 'TLT.csv'), 'TLT', None)
    
    # Cerebro
    cerebro = bt.Cerebro()
    cerebro.adddata(data0)
    
    # Broker
    start_capital = 10000
    myBroker = bt.brokers.BackBroker()
    comminfo = CommissionFF
    myBroker.addcommissioninfo(comminfo)
    myBroker.set_cash(start_capital)
    cerebro.broker = myBroker
    


  • ok, my bad, very stupid issue. I'll now experiment with the use of a data line. I'll keep you posted.
    Sorry for the mistake.

    this line should be changed:

    comminfo = CommissionFF
    # must be changed to 
    comminfo = CommissionFF()
    

    regards,
    Lamp'



  • Finally, managed to spend some time on this, Here is the final code for the benefit of others

    class CommissionFF(CommInfoBase):
        params = (
            ('commtype', CommInfoBase.COMM_FIXED),
            ('commission', 0.0),
            ('commtype', None),
            ('interest_long', True),
            ('spread_long', 0.0050), # FF + 50bp
            ('spread_short', -0.0050) # FF - 50bp
        )
    
        def _get_credit_interest(self, data, size, price, days, dt0, dt1):
            # (days / 365) * abs(size) * price * (interest + spread)
            # long: positive commission (i.e. debit)
            # short: negative commission (i.e. credit)
            if size > 0: # Long
                return (days / 365) * size * price * max(data.fed_fund[0] + self.params.spread_long, 0)
            else: # Short
                return (days / 365) * size * price * max(data.fed_fund[0] + self.params.spread_short, 0)
    


  • @lampalork why don't you use interest for short interest and interest_long for long interest both from class CommInfoBase.



  • @André-Tavares said in Custom Commission Scheme that take a timeseries for Interest:

    interest_long

    to my knowledge interest_long is a boolean flag not a float


Log in to reply
 

});