Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Need a little python help...

Okay so here's the problem:

I'm looping through data of diffrent timeframes, which is saved in a dictionary (keyed by sid) of lists (context.candlestick_"timeframe")

        data_handle = "context.candlestick_" + timeframe  
        if len(data_handle[sid]) > 2:  

-> Runtime exception: IndexError: string index out of range

Strangely enough it seems to work like this once and another time where it's mostly the same it doesn't.

I've also tried using:
if len("context.candlestick_%s[sid]" % (timeframe)) -> Same error
Does len() put out the length of the string or the length of the list (which is what I want, and expected it to do especially in the first code)?

Please let me know if there is a smarter and most importantly working way of doing this, as i can't find a solution right now. Thanks!

5 responses

Hi Johann,

The issue here is that the variable "data_handle" is a string variable. That's why you're getting the string index out of range error. I'm not exactly sure what you are trying to store in context.candlestick, but you are going to want to access that data with a [] notation.

So if context.candlestick is a dictionary of lists, you'll want to access those lists by context.candlestick[sid], which will return a list to you. Right now, you are just setting data_handle to be a string. The reason you might not always get the error is because the sid is an int, which is accessing part of the string.

Here's an example:

x = "a_sample_string"  
x[2]  

This outputs 's'. But if you try:
x[200] You'll get the error IndexError: string index out of range

If you have the rest of your code, I'd be happy to give you more specific advice on how to access this data.

Thanks!
Sam

I thought about that aswell, however I do not know how else to piece together the "path" to the data.
Relevant Code pieces:

def initialize(context):  
 context.sids = [sid(24)]  
 context.timeframes = ["daily"]

    context.highs_daily = {}  
    context.init = False

def handle_data(context, data):

    if not context.init:  
        for sid in context.sids:  
            context.highs_daily[sid] = list()

    for sid in context.sids:  
        for timeframe in context.timeframes:  
            support_resistance(context, sid, timeframe)

def support_resistance(context, sid, timeframe):  
    data_handle= "context.highs_" + timeframe  
    if len(data_handle[sid]) > 2:  
        pass  

Thanks for your help! I left the other timeframes out for simplicity

So here's what happens when this line:

data_handle= "context.highs_" + timeframe  

is executed:
data_handle is assigned to be the string "context.highs_daily", NOT the dictionary context.highs_daily. So when you execute this line:
if len(data_handle[sid]) > 2: data_handle[24] evaluates to the 25th (0-based indexing) letter of "context.highs_daily". You then get a IndexError since "context.highs_daily" doesn't have than many strings.

Here's how you can handle it:
def initialize(context): context.sides = [sid(24)] context.timeframes = ["daily"] context.highs = dict() for timeframe in context.timeframes: context.highs[timeframe] = dict() context.init = False

def handle_data(context, data):  
    if not context.init:  
        for timeframe in context.timeframes:  
            for sid in context.sids:  
                context.highs[timeframe][sid] = list()  
    for sid in context.sids:  
        for timeframe in context.timeframes:  
            support_resistance(context, sid, timeframe)  
def support_resistance(context, sid, timeframe):  
    data_handle= context.highs[timeframe]  
    if len(data_handle[sid]) > 2:  
        pass  

Right.... I really shoud have thought of that myself little embarressed. Thanks

No need to be embarrassed! Python has dynamic typing, which makes life a lot easier 99% of the time, but it can also make it a bit harder to predict what a variable actually is sometimes. Glad I could help!