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

Easier way to access "active" orders



  • Hi everyone in the Backtrader Community,

    I just started using Backtrader and the more I learn the more I love it! I've messed around with some simple algorithms and figured I wanted to implement a "max holding period" such that if a criteria for a centain stock hasn't been met, it'll just sell if it passes the period.

    Right now I have a working implementation like this:

    from datetime import datetime
    import pandas as pd
    import backtrader as bt
    from collections import defaultdict
    
    # Create a subclass of Strategy to define the indicators and logic
    
    class SmaCross(bt.Strategy):
        # list of parameters which are configurable for the strategy
        params = dict(
            pfast=10,
            pslow=30
        )
    
        def __init__(self):
            self.bar_executed = {}
            
            self.inds = defaultdict(dict)
            
            for d in self.datas:
                self.inds[d]['smaf'] = bt.ind.SMA(d, period=self.p.pfast)
                self.inds[d]['smas'] = bt.ind.SMA(d, period=self.p.pslow)
                self.inds[d]['crossover'] = bt.ind.CrossOver(self.inds[d]['smaf'], self.inds[d]['smas'])  
                
        def notify_order(self, order):
            if order.status in [order.Completed, order.Margin]:
                
                if order.isbuy():
                    self.bar_executed[order.data._name] = bt.num2date(order.executed.dt)
                    
                    print(['Order',order.data._name,
                           'BUY EXECUTED', 
                           'Price', '{:.4f}'.format(order.executed.price),
                           'Cost', '{:.4f}'.format(order.executed.value),
                           'Time', '{}'.format(bt.num2date(order.executed.dt))])
        
                else:
                    if order.data._name in self.bar_executed.keys():
                        self.bar_executed.pop(order.data._name)
                        
                    print(['Order',order.data._name,
                           'SELL EXECUTED', 
                           'Price', '{:.4f}'.format(order.executed.price),
                           'Cost', '{:.4f}'.format(order.executed.value),
                           'Time', '{}'.format(bt.num2date(order.executed.dt))])
    
        def next(self):
            
            # for every stock in my data
            for d in self.datas:
    
                # if no position is open on this stock
                if not self.broker.getposition(d):
                    if self.inds[d]['crossover'] > 0:
                        self.buy(d)
    
                elif self.inds[d]['crossover'] < 0:
                    self.close(d)
                
                elif self.broker.getposition(d):
                    timeNow = d.datetime.datetime()
                    holdingTime = (timeNow - self.bar_executed.get(d._name, timeNow)).days
                    if holdingTime > 100:
                        self.close(d)
    

    So basically I keep track of open positions in the bar_executed dictionary which is being populated in the notify_order function, with their ._name and the time they where executed.

    Is this the right way to do it?



  • if it works correct, than yes.


Log in to reply
 

});