Back to Community
Buying negative shares and selling positive shares?

In the following algo I attempt to log all my transactions for debugging purposes. My logs show that I am buying positive and negative amounts of shares and selling positive and negative amounts of shares. I do not understand how this is possible given the code provided.

Leverage = .95

def initialize(context):  
    set_symbol_lookup_date('2012-01-01')  
    set_universe(universe.DollarVolumeUniverse(floor_percentile=50.0, ceiling_percentile=51.0))  
    schedule_function(HandleExits)  
    schedule_function(HandleEntries)  
def handle_data(context, data):  
    positions = context.portfolio.positions  
    record(Leverage      = context.account.leverage)  
    #record(OpenPositions = sum([1 for sid in positions if positions[sid].amount > 0]))  
def HandleEntries(context, data):  
    positions = context.portfolio.positions  
    openLongPositions = [sid for sid in positions if positions[sid].amount > 0]  
    eligible = []  
    for stock in data:  
        tradeday = data[stock].datetime  
        current_price  = data[stock].price  
        moving_avg_20  = data[stock].mavg(20)  
        moving_avg_50  = data[stock].mavg(50)  
        moving_avg_200 = data[stock].mavg(200)

        if moving_avg_50 > moving_avg_200:  
            if (stock not in openLongPositions and not get_open_orders(stock)):  
                eligible.append(stock)

    eligible = eligible + openLongPositions  
    eligibleCount = float(len(eligible))  
    for stock in eligible:  
        buy_order_id = order_target_percent(stock, (1.0 / eligibleCount) * Leverage)  
        buy_order = get_order(buy_order_id)  
        if buy_order:  
            print "Bought %s shares of %s on %s for %s." % ((buy_order.amount), (stock.symbol), (tradeday.strftime('%m/%d/%y')), (data[stock].price))  
def HandleExits(context, data):  
    for stock in data:  
        tradeday = data[stock].datetime  
        current_price  = data[stock].price  
        moving_avg_50 = data[stock].mavg(50)  
        moving_avg_200 = data[stock].mavg(200)  
        if (current_price < moving_avg_50):  
            sell_order_id = order_target_percent(stock, 0.0)  
            sell_order = get_order(sell_order_id)  
            if sell_order:  
                print "Sold %s shares of %s on %s for %s." % ((sell_order.amount), (stock.symbol), (tradeday.strftime('%m/%d/%y')), (data[stock].price))

Also, does anyone know how I could sell a stock that I purchase if it falls 8% below my original purchase price? I'm not sure how to keep track of the purchase price of each stock I buy. A stop loss order is probably the best solution, but I am not sure how to incorporate that into my logic.

7 responses

I prefer to do stop loss orders by hardcoding them into my algorithm rather than rely on the program's stop loss order type.

Lets say that you want to buy either SPY or EFA depending on which has higher returns over the past 12 months. On your first month, you buy 100 shares of SPY. You also want to code a stop loss. The easiest way would be to use order_target_percent and use 0%. Sounds reasonable so far. In the next month, your algo tells you to buy EFA so it sells its SPY shares. Unexplicably you're leveraging 2 months later! why?
Because order_target_percent generates an order based on how much you are holding at the time you call the function. So by the time you sell your SPY manually, an order to sell 100 is still pending.

So you have to code in a cancel_everything() procedure. I copied one in my other thread.

For some reason, even this is quite unreliable, and I can't track when and why I'm cancelling, so I decided to hardcode a stoploss procedure. To do this, I just created a dataframe that stores everything in my portfolio and the price purchased. This will have to be stored in the context container.

As for your first problem, can you provide an example of the log output?

Thanks for the reply Johnny. So from what I understand, I need to check for open orders before I sell something (and assume that it was actually sold when I buy something else) to prevent leverage and make sure stop loss orders work? Could you please provide an example/explain how to make a cancel_everything() procedure and how to hardcore a stop loss procedure? I'm pretty new, so sorry if that is a basic question. Here is a link to my (rather long) my output log:

http://pastebin.com/yMKLV28U

Side question: Any ideas on how to avoid hitting the logging limit? (The per call of handle_data limit as well as the hard cap)

Thanks for the reply Johnny. So from what I understand, I need to check for open orders before I sell something (and assume that it was actually sold when I buy something else) to prevent leverage and make sure stop loss orders work? Could you please provide an example/explain how to make a cancel_everything() procedure and how to hardcore a stop loss procedure? I'm pretty new, so sorry if that is a basic question. Here is a link to my (rather long) my output log:

http://pastebin.com/yMKLV28U

Side question: Any ideas on how to avoid hitting the logging limit? (The per call of handle_data limit as well as the hard cap)

@YQ, order_target() functions don't take open orders into account when making their target calculations. So this can result in the +/- swings around the target amount that you're seeing. To prevent this, add a check to skip a security if there are already pending open orders. Like this:

for stock in data:  
        if get_open_orders(stock):  
            continue  
        for stock in eligible:  
            buy_order_id = order_target_percent(stock, (1.0 / eligibleCount) * Leverage)  
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.

@Alisa @Johnny Even with the code Alisa suggested the algo is ordering both positive and negative amounts of shares. The added code did, however, prevent the algo from selling positive amounts of shares. (All the logs for selling are expected to be negative.) Also, I'm still confused on coding stop loss orders without the built in function.

Young Q., you can check to see whether this version of your algo has problems...

This is the "proper" way to work your MAs. I think I fiddled with the total MAs as a general filter, looks like it's kind of restrictive. But you can rework it as you see fit.

Clone Algorithm
10
Loading...
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
import talib

Leverage = .95

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
def initialize(context):  
    set_symbol_lookup_date('2012-01-01')  
    set_universe(universe.DollarVolumeUniverse(floor_percentile=99.0, ceiling_percentile=100.0))
    schedule_function(HandleExits)
    schedule_function(HandleEntries)
    schedule_function(RecordStatus)
    
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
def handle_data(context, data):  
    pass

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
def RecordStatus(context, data):
    positions = context.portfolio.positions
    record(Leverage      = context.account.leverage)
    record(OpenPositions = sum([1 for sid in positions if positions[sid].amount > 0]))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
def HandleEntries(context, data):  
    positions = context.portfolio.positions
    openLongPositions = [sid for sid in positions if positions[sid].amount > 0]

    closeDeck = history(200, "1d", "close_price").dropna(axis=1)
    closeDeck = closeDeck[[sid for sid in closeDeck if sid in data]]
    smaX      = closeDeck.apply(talib.MA, timeperiod = 32, matype = MAType.SMA).dropna()    
    smaY      = closeDeck.apply(talib.MA, timeperiod = 53, matype = MAType.SMA).dropna()
    smaZ      = closeDeck.apply(talib.MA, timeperiod = 74, matype = MAType.SMA).dropna()   

    smaCount = 0; smaCount2 = 0
    eligible = []
    for stock in smaZ:
        maX    = smaX[stock][-1]
        maY    = smaY[stock][-1]
        maZ    = smaZ[stock][-1]
        if (maX > maY): 
            smaCount2 += 1
        if (maY > maZ):
            smaCount += 1
            if (maX > maY):
                if (stock in openLongPositions or get_open_orders(stock)):
                    continue
                eligible.append(stock)
                
    record(SMACount      = smaCount)
    record(SMACount2     = smaCount2)
    record(AvailableLegs = len(data))
    #
    # Risk on / off filter
    #
    if (smaCount2 > smaCount and smaCount2 > len(data) * .5):
        eligible = eligible + openLongPositions
        eligibleCount = float(len(eligible))
        for stock in eligible:
            order_target_percent(stock, (1.0 / eligibleCount) * Leverage)  
    else:
        for stock in data:
            order_target_percent(stock, 0.0)  
            
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       
def HandleExits(context, data):  
    closeDeck = history(100, "1d", "close_price").dropna(axis=1)
    closeDeck = closeDeck[[sid for sid in closeDeck if sid in data]]
    smaY      = closeDeck.apply(talib.MA, timeperiod = 5, matype = MAType.EMA).dropna()
    smaZ      = closeDeck.apply(talib.MA, timeperiod = 84, matype = MAType.TRIMA).dropna()   

    for stock in smaZ:
        maY    = smaY[stock][-1]
        maZ    = smaZ[stock][-1]
        if (maY < maZ):
            if (context.portfolio.positions[stock].amount != 0):
                order_target_percent(stock, 0.0)
                print("<< MA Exit {0}".format(stock.symbol))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class MAType():
    SMA   = 0; EMA   = 1; WMA   = 2; DEMA  = 3; TEMA  = 4;    
    TRIMA = 5; KAMA  = 6; MAMA  = 7; T3    = 8
There was a runtime error.