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

Backtesting Option Strategies



  • Hi,

    given I am mainly interested in options, I would need to write data during strategy execution. I.e. I would write the option value into a line object at every time "next" is called in the strategy execution. In a way it's like creating data for a new underlying every time the strategy enters into some option.

    Unfortunately, I can't do that. Trying to overwrite the original input data to test it:

    def next(self):
    
        self.data_0[0] = 111
    

    seems to change the [-1] value only. Is it possible to change the [0] value of the time series during the strategy execution. In the reference indicators and the strategy are distinguished in terms of which index they can write on to my understanding. Other ideas on how to achieve the outcome are very welcome.

    Thank you!


  • administrators

    @1324535 said in Writing data at to [0] element of line:

     self.data_0[0] = 111
    

    @1324535 said in Writing data at to [0] element of line:

    seems to change the [-1]

    It, for sure, doesn't. If you really believe it to be so, a sample proving it would be much appreciated.



  • Here's a little example that seems to replicate what I struggle with (taken from your introduction post). I don't think values get written to [-1] anymore as I assumed initially after getting an unexpected result. This is the next step where I attempt to overwrite the close value:

    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('OLD Close, %.2f' % self.dataclose[0])
        
        self.data_0[0]=10
        
        self.log('NEW Close, %.2f' % self.dataclose[0])
    
        if self.position.size == 0:
            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 close
    
                    # BUY, BUY, BUY!!! (with all possible default parameters)
                    self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    self.buy()
    

    Output:
    Starting Portfolio Value: 100.00
    1995-02-01, OLD Close, 2.09
    1995-02-01, NEW Close, 10.00
    1995-02-02, OLD Close, 2.12
    1995-02-02, NEW Close, 10.00
    1995-02-03, OLD Close, 2.17
    1995-02-03, NEW Close, 10.00
    1995-02-03, BUY CREATE, 10.00
    1995-02-06, OLD Close, 2.19
    1995-02-06, NEW Close, 10.00
    1995-02-07, OLD Close, 2.19
    1995-02-07, NEW Close, 10.00
    1995-02-08, OLD Close, 2.17
    1995-02-08, NEW Close, 10.00
    1995-02-09, OLD Close, 2.15
    1995-02-09, NEW Close, 10.00
    Final Portfolio Value: 99.98

    Now given the code initiates only 1 buy order @ 10 and the close is 10 for all days, we would expect fin value = 100. This value changes if I extend the time series. Setting the data point to 10, doesn't seem to change it for all objects involved:

    self.getposition().price

    returns 2.17, which is the original value of the time series.


  • administrators

    @1324535 said in Backtesting Option Strategies:

    I don't think values get written to [-1]

    Because the platform doesn't as stated above.

    @1324535 said in Backtesting Option Strategies:

    Now given the code initiates only 1 buy order @ 10

    Your wish to execute at @10 with a Market order doesn't mean you get matched at 10.

    It would be nice, but in general the market has a different idea about which price it gives you.

    @1324535 said in Backtesting Option Strategies:

    we would expect fin value = 100

    Check the execution price and the expectation will soon vanish.

    @1324535 said in Backtesting Option Strategies:

    self.getposition().price
    returns 2.17, which is the original value of the time series.

    A Position is not a data. You are checking the actual average price of the position you have taken. You are not checking the close price of anything.



  • Thanks for your message. Please ignore the [-1] issue, as that is not a problem indeed. Let me try to be more clear based on the example above: I would like to write values to a dummy time series. And I would like those new values to be used for the order as well.

    Now, what's happening above is the following: I write a value of 10 in the time series, overwriting the initial value of 2.17 for the day the order is executed. Yet the order is filled at 2.17, which means overwriting the initial value was not successful.
    The portfolio value is measured for an order based on the initial time series again showing I cannot overwrite the initial data during a next step as I try to do. A static time series cannot create pnl.

    What I suspect is that the time series of which I change values is not shared across all objects, hence the old value appears again.

    I would really appreciate any hint/idea on how you would look at option strategies. Think of different expiries/strikes. There is just no way you can pre-compute all of that. Anyone out there who has worked something like that? I am really only after backtesting, no execution.

    Cheers


  • administrators

    @1324535 said in Backtesting Option Strategies:

    Now, what's happening above is the following: I write a value of 10 in the time series, overwriting the initial value of 2.17 for the day the order is executed. Yet the order is filled at 2.17, which means overwriting the initial value was not successful.

    Not. It means you don't understand how order matching works.

    @1324535 said in Backtesting Option Strategies:

    What I suspect is that the time series of which I change values is not shared across all objects, hence the old value appears again.

    Very wrong suspicion. To start with there is only one instance of the data series, so it would be really difficult for any change not to be shared across all objects.

    1. If you want to change the values of an incoming data series, the best way is to apply a Filter to the data series. You may of course change that directly in next, but the indicators on that data series will be calculated using the original values and the new indicators will be calculated using a value which is changed manually.

    2. When you see a price bar (i.e.: the OHLC values) it means the prices are gone. You see the close because it has already happened. You cannot get matched at the close price at will simply because you want. You are issuing a Market order and this will be matched against the next incoming price, which unless you are working with Ticks (in which case we could say you get matched with the next tick), get matched to the open component of the next OHLC combination.

    See: Docs - Order Management and Execution

    If you want you can in any case cheat and use cheat-on-close (yes, it's called cheat-on-close because you are cheating). See: Docs - Broker](https://www.backtrader.com/docu/broker.html)