Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Long only results in short positions

I must be missing some basic assumptions about the operation of the percent rebalancing aspect of "order_target_percent()" as I would never have expected to see a short position (negative position.amount) come through a buy long only with a set_long_only() declared in initialize().

Yet some how the code in this strategy produces short positions.

This matters as I've got my TrailingStop code that automatically determines side for all positions and then automatically assigns a trailing stop based on that side. If we "were" long, and a trailing stop was set to protect that long position, but somehow we're now short (due to the mechanism within order_target_percent() I'm guessing), this throws my TrailingStop code against the wall (SPLAT!). I'm now exiting a short position I never thought I'd have.

Can anyone clue in this dazed and confused soul?

8 responses

I've seen something similar when I put in an order_target_percent() order while an existing order_target_percent() order is still open for that security. When I put in a check for open orders in that security before every order the problem went away, so you can use that for a quick fix.

def has_orders(context):
# Return true if there are pending orders.
has_orders = False
for sec in context.secs:
orders = get_open_orders(sec)
if orders:
for oo in orders:
message = 'Open order for {amount} shares in {stock}'
message = message.format(amount=oo.amount, stock=sec)
log.info(message)

        has_orders = True  
return has_orders  

Sometimes I decrease the initial money to, say, 10K, then problem solved. I guess it's because if it's 1M there will be no enough liquidity, and open orders get accumulated.

@Kevin Q. Added test for open orders which eliminated the short positions. Thanks.

    for stock in data:  
        if (get_open_orders(stock)):  
            continue  
        order_target_percent(stock, 1.0 / stockCount)  

Oddly there was just one short, at the end of the run...???

2014-11-21PRINT!!! Short position EWZ qty: -348

For the Quantopian folks, I haven't looked at your underlying code but I assume that the order_target_percent() function puts in new orders based on existing positions without consulting pending orders. On long closeouts this leads to unexpected short positions, on shorts it leads to runaway short positions. You may want to put a warning in the documentation to check for open orders before using this function as a short term fix, and long-term you might want to consider a more defined way for the function to handle open orders. Counting them when calculating percentages would seem to make the most sense, but there may be issues with that I haven't thought of.

Help says: "Specify long_only to prevent the algorithm from taking short positions." Above shows that is not so.
"does not apply to existing open orders or positions in your portfolio" sounds like set_long_only() means -- first transaction only per sym buy only, otherwise no shorting restrictions, because once transacted, always in portfolio.positions even if zero.
You need to write your own conditions to prohibit shorting.

@Kevin, yes the order_target functions only consider the existing positions, not the open orders, when making their target calculations. I think this behavior can be improved, and in the meantime, we can add this caveat to the help documentation.

You found the right fix - to check for open orders before making further calculations.

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.

Handling the tedious intricacies of open orders, cancels, cancel-too-lates, late-reported-fills etc is exactly what it would be helpful if Quantopian did! If everyone's algorithm needs the same wall of boilerplate python to handle too-common corner cases, then I think the platform has fallen short...

@Simon T., Indeed! Pareto, Pareto, where for art thou Pareto!

You should see some of the order handling contingency trees we've had to build. 20% straight arrow, shoot straight through. 80% nightmare of special FIX messages (some standard -- HA!), special verbiage on broker option comments; broker A can't do size amends so must convert to cancelreplace; broker B can't handle price cancelreplace, have to submit cancel and then new limit/stop. It never ends.

Traders just want to trade; quants just want to quant. Systems are supposed to deal with the ugly underbelly of broker foibles and expectation exceptions. But, it's no easy task and assumptions must be made along the way. Herding cats down the runway, some are bound to get loose.