Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Momentum trading

I've been trying to implement a momentum trading strategy recently.
Can someone tell me a good way of making this algo only buy the stock which has had the highest price increase in the last year?

Thanks,
-Jeff

11 responses

I suggest a primer to python programming, otherwise even such a task could get frustrating. A good one is Zed Shaw's Learn Python the Hard Way. After that a pandas tutorial is quite handy.

Apart any other coding style consideration, don't call history() function in a loop, it already returns a data structure with values for all securities so you just need to call it once. Maybe the call is cached but if it's not you'd end making a lot of calls for no reason.

I'd rewrite it using pandas for evaluating the momentum percentage and for finding the best security in each loop in the following way:

def initialize(context):  
    set_universe(universe.DollarVolumeUniverse(  
        floor_percentile=98, ceiling_percentile=100))  
    # set_do_not_order_list(security_lists.leveraged_etf_list)  
    schedule_function(daily_handle_data,  
                      date_rules.every_day(),  
                      time_rules.market_open(minutes=5))

def handle_data(context, data):  
    return

def daily_handle_data(context, data):  
    # Fetch history, evaluate percent change, slice out the values' row  
    best_performer = history(252, '1d', 'prices').pct_change(251).iloc[-1].idxmax()

    # This is running every day, 5 minutes after US market open  
    order_target_percent(best_performer, 0.1)  

Thanks Andrea!

I have another question. How could I use this to make the algo buy the top 2 performers?

I checked the documentation and didn't see any way of using idxmax() to select the second best stock

I guess it depends on what documentation you did check, but with a max function you will hardly get two results.

If you really want to stick using idxmax() you could get the history(252, '1d', 'prices').pct_change(251).iloc[-1] Serie, filter out the security you get from the first call and then a new call on this filteres Series would return the second best performer.

Personally I'd sort the Serie instance and take the last two objects (or first two, according to sorting criteria).
Something like

    history(252, '1d', 'prices').pct_change(251).iloc[-1].sort()[-2:]  

Running it like this:

b = history(252, '1d', 'price').pct_change(251).iloc[-1].sort()  

returns a list of "None"s. Is there some other sort function that might work?

Possibly sort is a method that performs in-place sorting, do the assignment first, then the sorting an another row.

I don't see anything horrendous in your code (but I'm not Python purist at all). I have to say I long dropped the habit of aligning equal signs in assignments, that somehow works when you have variable names of comparable lengths, but if you happen to have foo, bar, and should_raise_supercalifragilisticexpialidocious it's uglier. Now I just go with autopep8.

What I'd really change in that code is the literal string "Code block framework" - I'd make that a comment - and the function naming, I like non class objects to start with lower case, this regardless of the '_' separator or camel-case.

The framework is actually really nice, I came to a similar approach (altho' not so widely structured) when I moved updating of stop orders to a scheduled function executed before the main handle function.

I implemented a small logging facility as well, but in a totally different manner, I was trying to overcome the backtester row limits so I buffered the output and used levels, so every block of code logs to a different level and a variable on top states what levels are going to be printed.
Debugging in the IDE is quite hard due to both the custom debugger and having the webapp, I wish I could just use remote-pdb (or something like that) from a regular terminal…

@Andrea D., So you build up N log statements in a cache and then dump when the cache reaches N + 1? How do you dump the last period's cache of logs? I'm sure we'd all benefit from knowing your technique -- unless you've shared it elsewhere here.

No, it's just a matter of convention, I use a custom mylog() function and call flush_log() at the end my main function.

It's a practical matter for me, I do this because I find it easier than going back and forth through the code to add/remove log lines: I just call my_log() everywhere and then enable/disable the levels in which I'm interested.

Only the flush_log function calls a log.* function, so the algorithm never consume the two available lines per loop and never skip output.
Be warned that there's a char limit per lines, about 1000 chars net of the date and function name.

The logging thing is really nothing fancy, anyway I'll push an example.

@Market tech
Thanks a ton for posting your algo. It's really interesting.
I tried using set_universe instead of just the stocks that you listed, but I got an error. Apparently using the universe interferes with your calculation of "tempCollection." Specifically, it says that ROC is undefined. Do you know why this would be?

I really prefer to use set_universe so any help would be much appreciated.

Updated: simple protection code added

@Jeff, here's an alternative.

Python purists generally cringe when they see my code. (I take a little pleasure in that). But for me clarity is king.

There's much more code here than many are prepared to deal with. But the modularity of the implementation supports expansion. Various stops, added entry filters, additional ranking can all be added without too much disruption of the supporting code. Additional module methods can be found by searching for this phrase "Code block framework"

If it helps great. If not...