Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Major Issue? Settled vs Unsettled Cash Reporting

I've seen this issue brought up a couple of times (https://www.quantopian.com/posts/one-problem-with-interactive-brokers) but have not seen a resolution, at least publicly in the forums yet. It seems context.portfolio.cash is currently pulling data from the IB "cash" field. The problem with this is IB includes unsettled cash in that value. This is a pretty big issue if you are trading using a non margin account and do not want to keep a 100% cash reserve to cover unsettled cash. It also affects backtest performance as algo's are able to spend cash that is not really "available" yet. I would assume the solution would be as simple as Quantopian adding another option to pull the "buying power" field from IB or something similar which excludes unsettled cash.

If that is not possible for whatever reason, or as an interim solution, can anyone think of a way to account for unsettled cash? Maybe something like summing the prior 4 days sells and subtracting that from context.portfolio.cash?

9 responses

Hi Jared,

I'd recommend to use a cash buffer when you place your trades in your live trading algorithm. This way, you'll have a small amount of cash on reserve. If you're looking for an example, this algorithm uses a 1% cash buffer and distributes 99% of the portfolio cash equally among 9 ETFs: https://www.quantopian.com/posts/rebalance-algo-9-sector-etfs

We're also working on making IB account information available to your algorithm, and this will give you more control to query for settled cash and other metrics. When this work is complete we'll make a more formal announcement.

Cheers,
Alisa

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.

Hi Alisa, the issue lies more with certain momentum algos (and others I'm sure) that may close out an entire position and then try to use that money to purchase another security as soon as the same day. You would never be completely covered unless you maintained a cash reserve equal to the amount your investing.

Hello Jared,

I haven't tried paper/live trading at IB yet, but I'm wondering if the information you need is in the open orders? When does Quantopian indicate that a sell order is closed? After it is completely settled? Or immediately after the execution/transaction?

Grant

Grant, if going by the notion that a sell order is "closed" when the funds are able to be spent again, Quantopian closes the sell order immediately, as in the very next bar I'm assuming. I've run backtests where those sell funds have been spent again 10-15 mins later. In a real world environment I guess it's not a huge deal if Quantopian only attempts to place the buy trade once and then stops for the rest of the day if it is rejected for insufficient funds. If it keeps attempting to place it that might be a different story from IBs perspective. It can really affect backtest results though as it's almost operating on a margin basis.

Jared, I ran into this when I launched my first live algo as well, and it can be a pain. Giving you access to the different fields available in IB is a problem under active development, but it's not there yet. In the meantime you'll have to approximate your available cash by doing some bookkeeping in your code. The settlement period is 3 days (roughly), so if you would like to accurately backtest, any cash from sales will have to be subtracted out until the settlement period has elapsed. I just threw together an outline of one way to do this, hopefully you will be able to apply the concept to your algo.

I ended up just applying for a margin account with IB, it's simpler, and I got approved without any fuss. Hope this helps

David

class UnsettledCash(object):  
    def __init__(self, period=None):  
        self.period = period  
        self.ledger = {}

    def post_transaction(self, amount):  
        dt = get_datetime()  
        if dt not in self.ledger:  
            self.ledger[dt] = []  
        self.ledger[dt].append(amount)

    def unsettled_cash(self):  
        now = get_datetime()  
        amount = 0  
        for dt in self.ledger:  
            if now - dt < self.period:  
                amount += sum(self.ledger[dt])  
            else:  
                del self.ledger[dt]  
        return amount  


def initialize(context):  
    context.ledger = UnsettledCash(period=datetime.timedelta(days=3))

def handle_data(context, data):  
    stock = sid(8554)  
    price = data[stock].price  
    amount = -10  
    order(stock, amount)  
    context.ledger.post_transaction(abs(price * amount))  
    cash = context.portfolio.cash - context.ledger.unsettled_cash()  

David perhaps you could use a defaultdict+deque to simplify your UnsettledCash object.

David, thanks for the push in the right direction. I'm trying to work my way through your code but am definitely a novice when it comes to python (or any code for that matter). Morton, I would definitely be interested in hearing more about how this code could be simplified.

I am sure there are several more elegant ways to do this. A more robust option would be to use the order ids returned by the order functions. The function call order(stock, n) returns a hash id for that order, and get_order(some_id) returns an object containing the details of the order. Using the actual order details will allow you to filter them by date and account for filled/unfilled portions of the orders.

Jared, welcome to the world of writing code, Python is a great language for beginning to advanced developers. Programming puzzle sites are a fun/effective way to develop problem solving skills, CheckIO and Project Euler are a couple good ones. Everything comes with time, all you have to do is keep at it.

Hello Alisa, and David,

In addition to making more IB account information available to a live algorithm, will you also be modifying the backtester, so that trading with IB can be more accurately modeled?

Grant