Back to Community
Track Orders

An example that tracks orders / fills; track_orders() should be largely plug-n-play.
Edit: See below for code and notes.

The output is improved since this was first posted. The original ...

2013-07-17 track_orders:107 INFO Sell -86 TSLA now 120.3 target 164.86  
2013-07-26 track_orders:107 INFO Buy 102 STX at 41.05  
2013-07-29 track_orders:107 INFO  Bot 102 STX at 40.3  
2013-07-29 track_orders:107 INFO Buy 53 STX at 40.3  
2013-07-30 track_orders:107 INFO  Bot 53 STX at 41.25  
2013-07-30 track_orders:107 INFO Buy 25 STX at 41.25  
2013-07-31 track_orders:107 INFO  Bot 25 STX at 40.9  
2013-07-31 track_orders:107 INFO Sell -180 STX now 40.9 target 55.75  
2013-08-27 track_orders:107 INFO  Sold -86 TSLA at 167.0  
9 responses

Gary,

Wow, this is awesome. I think a lot of people will find this super useful. I've added a version that tracks stops as well:

Clone Algorithm
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
'''

track_orders() example.
Logs orders after entered and/or fill.
Includes LimitOrder() to sell only when price has gone up enough.

https://www.quantopian.com/posts/track-orders

'''

profit  = 1.37  # ratio
buy_dip =  .89  # ratio
window  = 7     # lookback

def initialize(context):
    context.stocks = symbols('STX', 'TSLA')
    context.orders = {}    # Keys are order id's, values are orders.
    context.prices = {}    # Keys are symbols, values are lists of prices.
    for s in context.stocks:
        context.prices[s.symbol] = []

    schedule_function(func = track_orders, date_rule = date_rules.every_day())
    schedule_function(func = summary, date_rule = date_rules.every_day())

def handle_data(context, data):
    for sec in data:
        if get_open_orders(sec):  # Skip frame strategy if open orders
            continue              #    for this security.

        sym      = sec.symbol
        cash_per = context.portfolio.cash / len(context.stocks)
        shares   = context.portfolio.positions[sec].amount
        cost_b   = context.portfolio.positions[sec].cost_basis
        price    = data[sec].price
        buy_num  = int( cash_per / price )
        context.prices[sym].append(price)
        context.prices[sym] = context.prices[sym][-window:]

        if dip(context, sym, price):    # B u y
                order(sec, buy_num)

        elif shares:                    # S e l l using limit
            target_price = cost_b * profit
            order(sec, -shares, style=LimitOrder(target_price))

        record(cash      = context.portfolio.cash)
        record(portfolio = context.portfolio.portfolio_value)

def track_orders(context, data):
    '''
        Log orders after they are created or filled.
    '''
    orders = []          # Any current order id's that are visible, for later.
    msg1 = []; msg2 = [] # For logging.

    # Open orders
    for sec, oo_for_sid in get_open_orders().iteritems():
        sym = sec.symbol
        for o in oo_for_sid:    # Orders per security
            orders.append(o.id)
            if o.id in context.orders:
                if o.filled > context.orders[o.id]['filled']:
                    # Filled at least some
                    trade = 'Bot' if o.amount > 0 else 'Sold'
                    diff  = o.filled - context.orders[o.id]['filled']
                    msg2.append(
                        '  {} {} {} at {}\n'.format(trade, diff, sym, data[sec].price)
                    )
                if o.filled == o.amount: # Complete so drop tracking
                    del context.orders[o.id]
            else:   # New order
                trade = 'Buy' if o.amount > 0 else 'Sell'
                if o.limit:  # Limit order
                    msg2.append(
                        '{} {} {} now {} limit {}\n'.format(
                            trade, o.amount, sym, data[sec].price, o.limit
                        )
                    )
                elif o.stop:
                    msg2.append(
                        '{} {} {} now {} stop {}\n'.format(
                            trade, o.amount, sym, data[sec].price, o.stop
                        )
                    )
                else:        # Market order
                    msg2.append(
                        '{} {} {} at {}\n'.format(
                            trade, o.amount, sym, data[sec].price
                        )
                    )
                context.orders[o.id] = o

    # Stored orders
    to_delete = []
    for id in context.orders:
        if id not in orders:
            # Completed order
            o     = context.orders[id]
            sym   = o.sid.symbol
            trade = 'Bot' if o.amount > 0 else 'Sold'
            diff  = o.amount - o.filled
            msg1.append(
                '   {} {} {} at {}'.format(trade, diff, sym, data[o.sid].price)
            )
            to_delete.append(id)
    for d in to_delete: # (can't delete while iterating above, hence this)
        del context.orders[d]

    # Logging
    for m in msg2:
        msg1.append(m)
    for m in msg1:
        log.info(m)

def dip(context, sym, price):
    # Return whether price has dropped beyond the buy_dip ratio.
    price_hi = max(context.prices[sym])
    if price_hi * buy_dip > price:
        return True
    return False


def summary(context, data):
    '''
        Summary processing

        https://www.quantopian.com/posts/run-summary
    '''
    # Need a couple of imports, you might need to comment these out if already imported.
    #   That's pretty much the only change that might be necessary.
    from pytz import timezone
    import re

    # Yes try/except is narly yet makes to work with set_universe etc.
    # Is there a better way?  An -| if 'books' in context: |- didn't work.
    try:
        context['books']    # See if this key exists yet.
        b = context.books   # For brevity.
    except:
        '''
            Preparation. Initialize one time.
        '''
        cash = context.portfolio.starting_cash
        context.books = {   # Starting cash value from GUI or live restart...
            'cash'          : cash,
            'init_cash'     : cash,
            'cash_low'      : cash,
            'shares'        : 0,
            'shares_value'  : 0,
            'count_buy'     : 0,       # Overall buy count, number of shares.
            'count_sell'    : 0,       # Overall sell count.
            'cnt_buy_evnts' : 0,       # Overall buy events count.
            'cnt_sel_evnts' : 0,
            'summary_print' : 0,
            'costs_total'   : 0,       # Commissions.
            'sids_seen'     : [],      # For set_universe since dynamic.
            'arena'         : None,    # To become 'backtest' or 'live'.
            'mode'          : None,    # To become 'daily' or 'minute'.
            'prep_prnt'     : '',
            'orders'        : {        # Keep orders for accounting.
                'open' : {},           # Orders not completely filled yet.
                'syms' : {},           # Dict of symbols with open orders,
            },                         #   can be used to not order over another.
            'first_trading_date' : str(get_datetime().date()),
        }

        b = context.books

        # First/last dates and
        #   Arena: backtest or live.  Mode: daily or minute.
        try:
            # Prep some environment info
            b['last_trading_date'] = re.findall('period_end=(.*?) ', str(sid))[0]
            arena     = re.findall('Live|Simulation', str(sid))[0]
            b['mode'] = re.findall('data_frequency=(.*?),', str(sid))[0]

            if arena == 'Live':
                b['arena'] = 'live'
            elif arena == 'Simulation':
                b['arena'] = 'backtest'
        except:
            log.info('Error in str(sid), summary will not print.')
            b['last_trading_date'] = 'unknown'
            b['arena'] = 'Arena unknown'
            b['mode']  = 'Mode unknown'

        # Show environment at the beginning of the run
        msg  = ' {0:s}\n  {1:s}  {2:s} to {3:s}  {4:s}  {5:s}\n'
        b['prep_prnt'] = msg.format(
            b['arena'],
            b['mode'],
            b['first_trading_date'],
            b['last_trading_date'],
            '   $' + "%.0f" % b['cash'],
            '  First bar stocks ({}) ...'.format(len(data)),
        )

        # Show current universe once
        for sec in data:
            if isinstance(sec, basestring):
                continue   # Skip any injected fetcher string keys.
            b['prep_prnt'] += (sec.symbol + ' ')
        log.info(b['prep_prnt'])

    '''
        Prepare individual securities dictionaries
          with dynamic set_universe, fetcher, IPO's appearing etc.
    '''
    for sec in data:
        if isinstance(sec, basestring):
            continue   # Skip any injected fetcher string keys.
        sym = sec.symbol
        if sym in b:
            continue
        if sec not in b['sids_seen']:
            # Scenarios with price missing ...
            price = data[sec].price if 'price' in data[sec] else 0
            b['sids_seen'].append(sec)
            b[sym] = {
                'init_price'    : price,  # Save for summary.
                'price'         : price,  # Most recent price.
                'cash_low'      : 0,      # Lowest level of cash.
                'balance'       : 0,      # For individual 'x' return.
                'shares'        : 0,
                'count_buy'     : 0,      # Individual buy number of shares.
                'count_sell'    : 0,
                'cnt_buy_evnts' : 0,      # Individual buy events count.
                'cnt_sel_evnts' : 0,
            }

    '''
        Accounting. Update the numbers, manage orders if any.
    '''
    accounting = {} # Locally, any orders ready to be counted.

    # Read open orders
    for security, oo_for_sid in get_open_orders().iteritems():
        sym = security.symbol
        for order_obj in oo_for_sid:
            # Convenience option to be able in handle_data to
            #   avoid ordering if an order already exists.
            b['orders']['syms'][sym] = 1

            # If an order not seen before, add for tracking
            if order_obj.id not in b['orders']['open']:
                b['orders']['open'][order_obj.id] = order_obj.filled

    # Take a look at current orders
    for id in b['orders']['open']:
        o = get_order(id)         # Current order, might be updated.

        # If filled is not zero, account for it
        if o.filled != 0:
            accounting[id] = o    # Set to account for filled.

            # Bugbug: The only way I could make sense of things so far ...
            # If filled is not amount (shares), that's a partial fill,
            #   cancelling remainder to simplify life.
            # ToDo: Not sure of official actual fill prices.
            if o.filled != o.amount:
                cancel_order(id)  # You might want to change/remove this.

    # Do any accounting, into books{}
    for id in accounting:
        sec             = accounting[id]['sid']
        sym             = sec.symbol
        commission      = accounting[id]['commission']
        filled          = accounting[id]['filled']  # Number filled, sell neg.
        if sec in data and 'price' in data[sec]:    # Update if available.
            b[sym]['price'] = data[sec].price
        lkp             = b[sym]['price']           # Last known price.
        transaction     = filled * lkp

        b[sym]['shares']  += filled      # The transaction on sell is negative
        b[sym]['balance'] -= transaction #   so this line adds to balance then.
        b[sym]['balance'] -= commission
        b['costs_total']  += commission

        if filled > 0:                          # Buy
            b[sym]['cnt_buy_evnts'] += 1
            b[sym]['count_buy']     += filled
        elif filled < 0:                        # Sell
            b[sym]['cnt_sel_evnts'] += 1
            b[sym]['count_sell']    += abs(filled)

        # Remove from the list, accounting done
        if sym in b['orders']['syms']:    # There's a scenario in multiple buys
            del b['orders']['syms'][sym]  #   where this key could be gone.
        del b['orders']['open'][id]

        # Overall keep track of lowest cash point
        cash_now = context.portfolio.cash
        if cash_now < b['cash_low']:
            b['cash_low'] = cash_now

            # An alert for negative cash unless you like "leverage"
            if b['cash_low'] < 0:   # Lowest cash points reached ...
                log.info(str(sym).ljust(5) \
                    + ' order for ' + (('$' + "%.0f" % transaction) \
                    + ',').ljust(8) + ' cash low: ' + str(int(b['cash_low']))
                )

        # And per symbol
        if b[sym]['balance'] < b[sym]['cash_low']:
            b[sym]['cash_low'] = b[sym]['balance']

    '''
        Show summary if this is the last bar
    '''
    last_bar_now = 0

    if not b['summary_print']:
        if context.books['arena'] == 'live':
            # When paper/live print summary every day end of day
            last_bar_now = 1
        elif context.books['arena'] == 'backtest':
            # Flag for summary output if last bar now
            bar = get_datetime()
            if b['last_trading_date'] == str(bar.date()):
                if b['mode'] == 'daily':
                    last_bar_now = 1
                elif b['mode'] == 'minute':
                    last_bar_now = 1

    if last_bar_now or b['summary_print']:
        '''
            Summary output to the logging window
        '''
        # Independent copy of context.books using dict() in case summary print
        #   is set to happen more than once in a run, due to concats below (+=)
        #   although the print any time is deprecated, couldn't find a way
        #   to make work with schedule_function.
        b    = dict(context.books)
        done = {}   # Protect against any listed twice.

        # Some overall values by adding individual values
        for sec in b['sids_seen']:
            if sec in done:
                continue

            # There's a problem with a dynamic run where a security
            #   can have dropped out of the picture, and its price
            #   is no longer accessible. Bad. Need help from Q.
            if sec in data and 'price' in data[sec]:
                b[sec.symbol]['price'] = data[sec].price

            sym    = sec.symbol
            shares = b[sym]['shares']
            b['count_buy']     += b[sym]['count_buy']
            b['count_sell']    += b[sym]['count_sell']
            b['cnt_buy_evnts'] += b[sym]['cnt_buy_evnts']
            b['cnt_sel_evnts'] += b[sym]['cnt_sel_evnts']
            b['shares']        += shares
            b['shares_value']  += (shares * b[sym]['price'])
            done[sec] = 1

        q__portfolio  = str(int(context.portfolio.portfolio_value))
        cash_end      = context.portfolio.cash
        init_cash     = b['init_cash']
        avg_init_cash = init_cash / len(b['sids_seen'])
        cash_low      = b['cash_low']
        my_portfolio  = cash_end + b['shares_value']
        cash_profit   = cash_end - b['init_cash']
        xval          = 'x0'
        max_spent     = init_cash - cash_low
        drawdown      = max(init_cash, init_cash - cash_low)
        cnt_b_evts    = ('  (' + str(b['cnt_buy_evnts']) + ' trades)').rjust(17)
        cnt_s_evts    = ('  (' + str(b['cnt_sel_evnts']) + ' trades)').rjust(17)
        untouchd      = '' if int(cash_low) <= 0 else \
                        '  (' + str(int(cash_low)) + ' unused)'
        neg_cash      = '' if int(cash_low) >= 0 else '                       ' \
                            + "%.0f" % cash_low + ' max negative cash'
        if drawdown  != 0:               # Pure profit over input used.
            xval      = 'x'  + "%.3f" % ((my_portfolio - init_cash) / drawdown)

        w1 = 16; w2 = 8  # Widths of columns
        outs = [
            '  QPortfolio: '.rjust(w1)+('$'+str(q__portfolio)) .rjust(w2),
            '   Buy Count: '.rjust(w1)+str(b['count_buy'])     .rjust(w2)+cnt_b_evts,
            '  Sell Count: '.rjust(w1)+str(b['count_sell'])    .rjust(w2)+cnt_s_evts,
            '  Shares Now: '.rjust(w1) + str(b['shares'])      .rjust(w2),
            'Shares Value: '.rjust(w1) + str(int(b['shares_value'])).rjust(w2),
            '    Cash Now: '.rjust(w1) + str(int(cash_end))         .rjust(w2),
            ' Cash Profit: '.rjust(w1) + str(int(cash_profit))      .rjust(w2),
            ' Commissions: '.rjust(w1) + str(int(b['costs_total'])) .rjust(w2),
            '   Max Spent: '.rjust(w1) + str(int(max_spent))        .rjust(w2)+neg_cash,
            'Initial Cash: '.rjust(w1) + str(int(init_cash))        .rjust(w2)+untouchd,
            '   Portfolio: '.rjust(w1)+('$'+str(int(my_portfolio))) .rjust(w2),
        ]
        out  = '_\r\n'
        for o in outs:
            out += (o + '\r\n')
        out += '        Return:  ' + xval + '   Profit/Drawdown\r\n'

        # -------------------------------
        # Individual securities detail
        # -------------------------------
        out_content_collections = []
        count_sids  = len(b['sids_seen'])
        sec_word    = ' security' if count_sids == 1 else ' securities'
        out_content = '_      ' + "%.0f" % int(b['init_cash'] / count_sids) \
                + ' average initial cash, ' + str(count_sids) + sec_word + '\r\n'
        lines_out   = 11    # Log in clumps to stay under logging limits.
        count_lines = 0
        col_widths  = {1: 8, 2: 7, 3: 7, 4: 12, 5: 8, 6: 8, 7: 9, 8: 9, 9: 8, 10: 9}
        header1 = [
        '',     'Return','Buy|','By|Sl','By|Sl', 'Price',  'Max', 'Cash','Shrs','Shrs'
        ]
        header2 = [
        'Symbol','Ratio','Hold','Count','Evnts','Strt|Now','Spent','Now','Now', 'Value'
        ]

        cc = 1  # Column count
        for h in header1:
            out_content += h.center(col_widths[cc])
            cc += 1
        out_content += '~\r\n' # Tilde at the end of line for replace-all in an editor
        # later after copy/paste, since new lines are gone at least on Windows.
        # Unfortunate to not be able to copy and paste results easily.

        count_lines += 1
        cc = 1
        for h in header2:
            out_content += h.center(col_widths[cc])
            cc += 1
        out_content += '~\r\n'
        count_lines += 1

        for sym in sorted(s.symbol for s in b['sids_seen']):
            balance      = b[sym]['balance']
            init_price   = b[sym]['init_price']
            shares       = b[sym]['shares']
            shares_value = shares * b[sym]['price']
            buy_hold     = 0.0
            xval         = 'x0'
            max_spent    = abs(b[sym]['cash_low'])
            drawdown     = min( avg_init_cash, abs(b[sym]['cash_low']) )
            if drawdown != 0:
                portf = balance + shares_value
                xval  = 'x' + "%.1f" % ((portf - drawdown) / drawdown)
                if xval == 'x-0.0' or xval == 'x0.0':  # Mainly clearing -0.0
                    xval = 'x0'    # -0.0 would have been something like -0.02
            if init_price:
                buy_hold = "%.1f" % ((b[sym]['price'] - init_price) / init_price)
                if buy_hold == '-0.0' or buy_hold == '0.0':
                    buy_hold = '0'
            content = [
                sym,
                xval,
                buy_hold,
                str(b[sym]['count_buy']) + '|' \
                    + str(b[sym]['count_sell']),
                str(b[sym]['cnt_buy_evnts']) + '|' \
                    + str(b[sym]['cnt_sel_evnts']),
                "%.0f" % init_price + '|' + "%.0f" % b[sym]['price'],
                "%.0f" % max_spent,
                "%.0f" % balance,
                shares,
                int(shares_value)
            ]
            cc = 1
            for c in content:
                out_content += str(c).center(col_widths[cc])
                cc += 1
            out_content += '~\r\n'
            count_lines += 1

            # Decide when to tuck a group away for later and
            #    start a new group, using modulus (remainder).
            if count_lines % lines_out == 0:
                out_content_collections.append(out_content)
                out_content = '_\r\n'       # Restart a group

        if count_lines % lines_out != 0:    # A few remaining lines.
            out_content_collections.append(out_content)

        log.info(out)        # The top, general overall output first.

        # Show the stored groups2
        for occ in out_content_collections:
            log.info(occ)

        # Add any other content you want ---------------------------
        out_content  = '_\n' # Underscore to a new line for left alignment,
                             #   '\n' by itself would be ignored/dropped.
        # Some variables or whatever you might want to add...
        out_content += ''

        log.info(out_content)

There was a runtime error.
Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Goodness, hopefully this can be moved out of people's algo code and into the quantopian core!

Thanks Seong, interesting thought Simon, suggest in initialize() a log_orders(stuff here) call implemented on Quantopian for as soon as trades happen.

Edit: Removed some content about stops

Last updated 2018-05-29 Faster when using 'symbols' for filtering

Updates
- Faster.
- Option to filter for a list of symbols.
- Handles Stop and Limit orders.
- Specify start and/or optional stop dates to hone in on a particular area while not overwhelming the logging window.
- Precedes each line with the minute of the day (more readable than the log line timestamp).
- Option to add order id's on each line.
- Option to add cash on each line.

About how to run this: Be sure its schedule_function is last, after any others.

def initialize(context, data):  
    [your things]  

Drop all of this at the end of initialize() and run it. Then you can move track_orders() if you want to.

    for i in range(1, 391):  
        schedule_function(track_orders, date_rules.every_day(), time_rules.market_open(minutes=i))

def track_orders(context, data):  
    '''  Show orders when made and filled.  
           Info: https://www.quantopian.com/posts/track-orders  
    '''  
    c = context  
    try: c.trac  
    except:  
        c.t_opts = {        # __________    O P T I O N S    __________  
            'symbols'     : [],   # List of symbols to filter for, like ['TSLA', 'SPY']  
            'log_neg_cash': 1,    # Show cash only when negative.  
            'log_cash'    : 1,    # Show cash values in logging window or not.  
            'log_ids'     : 1,    # Include order id's in logging window or not.  
            'log_unfilled': 1,    # When orders are unfilled. (stop & limit excluded).  
            'log_cancels' : 0,    # When orders are canceled.  
        }    # Move these to initialize() for better efficiency.  
        c.t_dates  = {  # To not overwhelm the log window, start/stop dates can be entered.  
            'active': 0,  
            'start' : [],   # Start dates, option like ['2007-05-07', '2010-04-26']  
            'stop'  : []    # Stop  dates, option like ['2008-02-13', '2010-11-15']  
        }  
        c.trac = {}  
        log.info('track_orders active. Headers ...')  
        log.info('             Shares     Shares')  
        log.info('Min   Action Order  Sym  Now   at Price   PnL   Stop or Limit   Cash  Id')  
    from pytz import timezone as _tz  # Python only does once, makes this portable.  
                                      #   Move to top of algo for better efficiency.  
    # If 'start' or 'stop' lists have something in them, triggers ...  
    if c.t_dates['start'] or c.t_dates['stop']:  
        _date = str(get_datetime().date())  
        if   _date in c.t_dates['start']:    # See if there's a match to start  
            c.t_dates['active'] = 1  
        elif _date in c.t_dates['stop']:     #   ... or to stop  
            c.t_dates['active'] = 0  
    else: c.t_dates['active'] = 1           # Set to active b/c no conditions.  
    if c.t_dates['active'] == 0: return     # Skip if not active.  
    def _minute():   # To preface each line with the minute of the day.  
        bar_dt = get_datetime().astimezone(_tz('US/Eastern'))  
        return (bar_dt.hour * 60) + bar_dt.minute - 570 # (-570 = 9:31a)  
    def _trac(to_log):      # So all logging comes from the same line number,  
        log.info(' {}   {}'.format(str(_minute()).rjust(3), to_log))  # for vertical alignment in the logging window.

    for oid in c.trac.copy():               # Existing known orders  
      o = get_order(oid)  
      if c.t_opts['symbols'] and (o.sid.symbol not in c.t_opts['symbols']): continue  
      if o.dt == o.created: continue        # No chance of fill yet.  
      cash = ''  
      prc  = data.current(o.sid, 'price') if data.can_trade(o.sid) else c.portfolio.positions[o.sid].last_sale_price  
      if (c.t_opts['log_neg_cash'] and c.portfolio.cash < 0) or c.t_opts['log_cash']:  
        cash = str(int(c.portfolio.cash))  
      if o.status == 2:                     # Canceled  
        do = 'Buy' if o.amount > 0 else 'Sell' ; style = ''  
        if o.stop:  
          style = ' stop {}'.format(o.stop)  
          if o.limit: style = ' stop {} limit {}'.format(o.stop, o.limit)  
        elif o.limit: style = ' limit {}'.format(o.limit)  
        if c.t_opts['log_cancels']:  
          _trac('  Canceled {} {} {}{} at {}   {}  {}'.format(do, o.amount,  
             o.sid.symbol, style, prc, cash, o.id[-4:] if c.t_opts['log_ids'] else ''))  
        del c.trac[o.id]  
      elif o.filled:                        # Filled at least some.  
        filled = '{}'.format(o.amount)  
        filled_amt = 0  
        #if o.status == 1:                   # Nope, is either partial or complete  
        if o.filled == o.amount:             # Complete  
          if 0 < c.trac[o.id] < o.amount:  
            filled   = 'all {}/{}'.format(o.filled - c.trac[o.id], o.amount)  
          filled_amt = o.filled  
        else:                                    # c.trac[o.id] value is previously filled total  
          filled_amt = o.filled - c.trac[o.id]   # filled this time, can be 0  
          c.trac[o.id] = o.filled                # save fill value for increments math  
          filled = '{}/{}'.format(filled_amt, o.amount)  
        if filled_amt:  
          now = ' ({})'.format(c.portfolio.positions[o.sid].amount) if c.portfolio.positions[o.sid].amount else ' _'  
          pnl = ''  # for the trade only  
          amt = c.portfolio.positions[o.sid].amount ; style = ''  
          if (amt - o.filled) * o.filled < 0:    # Profit-taking scenario including short-buyback  
            cb = c.portfolio.positions[o.sid].cost_basis  
            if cb:  
              pnl  = -filled_amt * (prc - cb)  
              sign = '+' if pnl > 0 else '-'  
              pnl  = '  ({}{})'.format(sign, '%.0f' % abs(pnl))  
          if o.stop:  
            style = ' stop {}'.format(o.stop)  
            if o.limit: style = ' stop () limit {}'.format(o.stop, o.limit)  
          elif o.limit: style = ' limit {}'.format(o.limit)  
          if o.filled == o.amount: del c.trac[o.id]  
          _trac('   {} {} {}{} at {}{}{}'.format(  
            'Bot' if o.amount > 0 else 'Sold', filled, o.sid.symbol, now,  
            '%.2f' % prc, pnl, style).ljust(52) + '  {}  {}'.format(cash, o.id[-4:] if c.t_opts['log_ids'] else ''))  
      elif c.t_opts['log_unfilled'] and not (o.stop or o.limit):  
        _trac('      {} {}{} unfilled  {}'.format(o.sid.symbol, o.amount,  
         ' limit' if o.limit else '', o.id[-4:] if c.t_opts['log_ids'] else ''))

    oo = get_open_orders().values()  
    if not oo: return                       # Handle new orders  
    cash = ''  
    if (c.t_opts['log_neg_cash'] and c.portfolio.cash < 0) or c.t_opts['log_cash']:  
      cash = str(int(c.portfolio.cash))  
    for oo_list in oo:  
      for o in oo_list:  
        if c.t_opts['symbols'] and (o.sid.symbol not in c.t_opts['symbols']): continue  
        if o.id in c.trac: continue         # Only new orders beyond this point  
        prc = data.current(o.sid, 'price') if data.can_trade(o.sid) else c.portfolio.positions[o.sid].last_sale_price  
        c.trac[o.id] = 0 ; style = ''  
        now  = ' ({})'.format(c.portfolio.positions[o.sid].amount) if c.portfolio.positions[o.sid].amount else ' _'  
        if o.stop:  
          style = ' stop {}'.format(o.stop)  
          if o.limit: style = ' stop {} limit {}'.format(o.stop, o.limit)  
        elif o.limit: style = ' limit {}'.format(o.limit)  
        _trac('{} {} {}{} at {}{}'.format('Buy' if o.amount > 0 else 'Sell',  
          o.amount, o.sid.symbol, now, '%.2f' % prc, style).ljust(52) + '  {}  {}'.format(cash, o.id[-4:] if c.t_opts['log_ids'] else ''))  

There appears to be a bug in your code Blue.
Error SyntaxError: unexpected character after line continuation character

for oid in c.trac.copy():
c.trac[o.id]['cb'] = c.portfolio.positions[o.sid].cost_basis \ <<< On this line continuation character
if c.portfolio.positions[o.sid].cost_basis else c.trac[o.id]['cb']

That's a revelation, the forum code adds two spaces at the end of almost every line instead of displaying code in its original form. You can remove the spaces after backslash in your code or copy/paste again, I switched them over to long lines above.

Thanks Blue. Amazing... such a $#!% load of work has gone into that, it is much appreciated!

Check out this post for more explanations from Blue on how track_order works
https://www.quantopian.com/posts/get-open-orders-on-a-sub-minutely-level#59503680de5db60010c41591

First off, let me say how much I appreciate you putting this together.

My question is: how did you find out what the different status numbers meant?

Such as o.status== 1 or o.status==2