Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
.properties and {dicts} and algos, oh my!

I have set myself the task of learning Python, or at least enough Python to learn how algos work and how to tweak them. Although I can get my head around most of the concepts in Python (variables, functions, If, ELIF, looping etc.) the area that I am really struggling with is the whole concept of using properties with objects, so for example:

myobject.myproperty

I just don't understand this bit of it at all - Is there some really simple tutorial that can explain how properties work and are applied to objects, specifically:

  • I am assuming that def initialize(context): is a function and not a class, and yet dot properties can be used with it; is that normal and to all intents and purposes do the dot properties work like they would with a class?
  • Is there a way to easily understand the overall concept of properties and how they work with objects, specifically {dicts}?
  • Can I assign properties to objects myself?
  • Is there a pre-defined list of properties that can be called?
  • How do I define properties that I want to call myself?

I must have looked at a dozen tutorials and I just cannot get my head around it. If anyone has any guidance or can point me at a tutorial that will specifically explain this (rather important!) part of Python, that would be great.

Thanks so much.

7 responses

If it might help toward the answers, this is from the data dictionary, something I had formatted manually and saved in a file:

 SIDData(  
   {  
      'sid': Security(  
             2174,  
             symbol        = u'DIA',  
             security_name = u'SPDR DOW JONES INDUSTRIAL AVER',  
             exchange      = u'NYSE ARCA EXCHANGE',  
             start_date    = datetime.datetime(1998, 1, 20, 5, 0, tzinfo=<UTC>),  
             end_date      = datetime.datetime(2013, 12, 27, 5, 0, tzinfo=<UTC>),  
             first_traded  = None  
          ),  
      'price':       148.14,  
      'open_price':  148.88,  
      'high':        149.2,  
      'low':         147.61,  
      'close_price': 148.14,  
      'volume':      5347802,  
      'type':        4  
      'vwap':        <function _transform at 0x9583aa0>,  
      'mavg':        <function _transform at 0x9583b18>,  
      'stddev':      <function _transform at 0x9583c08>,  
      'returns':     <function _transform at 0x9583b90>,  
      'dt':          datetime.datetime(2013, 9, 3, 0, 0, tzinfo=<UTC>),  
      'datetime':    datetime.datetime(2013, 9, 3, 0, 0, tzinfo=<UTC>),  
      'source_id':   'DynamicUniverseTradeSource43befd58175be9f1cde1965b3abd2fd3',  
      'MovingVWAPad9473767b9caa535f616974b59616c3': 148.14,  
   }  
 )

Extremely helpful - Thank you.

Is it possible to get a similar extract of what is contained in 'Context' or does that vary tremendously based on the initialize function?

Yes, maybe. This doesn't fully address the questions. I have some of those same questions and hope for discussion.

If try to print context from initialize, just results in something similar to 1970-01-01 PRINT qexec.algo.algoproxy.AlgorithmContext object at 0x7275c50,
however printing a sub-level works...

def handle_data(context, data):  
    print context.portfolio  

...and then after spending some time with the output, example:

 Portfolio(  
   {  
      'portfolio_value': 5000.0,  
      'cash':            5000.0,  
      'starting_cash':   5000.0,  
      'returns':         0.0,  
      'capital_used':    0.0,  
      'pnl':             0.0,  
      'positions_value': 0.0,  
      'start_date':      datetime.datetime(2013, 9, 1, 0, 0, tzinfo=<UTC>)  
      'positions': {  
           Security(  
                2174,  
                symbol        = u'DIA',  
                security_name = u'SPDR DOW JONES INDUSTRIAL AVER',  
                exchange      = u'NEW YORK STOCK EXCHANGE',  
                start_date    = datetime.datetime(1993, 1, 4, 5, 0, tzinfo=<UTC>),  
                end_date      = datetime.datetime(2013, 12, 27, 5, 0, tzinfo=<UTC>),  
                first_traded  = None  
           ): Position(  
                 {  
                   'amount':          0,  
                   'last_sale_price': 14.26,  
                   'cost_basis':      0.0,  
                   'sid': Security(  
                        2174,  
                        symbol        = u'DIA',  
                        security_name = u'SPDR DOW JONES INDUSTRIAL AVER',  
                        exchange      = u'NEW YORK STOCK EXCHANGE',  
                        start_date    = datetime.datetime(1993, 1, 4, 5, 0, tzinfo=<UTC>),  
                        end_date      = datetime.datetime(2013, 12, 27, 5, 0, tzinfo=<UTC>),  
                        first_traded  = None  
                    )  
                 }  
              )  
       },  
   }  
 )  

The Security() object is used as a dictionary key in one case and value in another.

If you are refering to propery objects, then they can be thought of as sugar for wrapping reads and writes to an attribute. For example, to create a read-only attribute, you may use:

class MyClass(object):  
    def __init__(self):  
        self._read_only_attr = 10

    @property  
    def read_only(self):  
        return self._read_only_attr

myobj = MyClass()  
print myobj.read_only  # prints 10, valid code.

# however:  
myobj.read_only = 'not 10'  # Raises: AttributeError: can't set attribute  

If you are refering to attributes in general, then we should start with what the syntax you describe actually means.
Fundementally, everything in python is an object. This means that classes, modules, functions, methods, string literals, and so on are all instances of classes.
For most cases, you may take your example of:
myobject.myattribute and replace it with:
myobject.__dict__['myattribute'] This is a simplification, but it may help to understand what this means first.
User defined attributes are merely stored in a dictionary on the object, and are looked up as strings.
Of course, it is better to use the myobject.myattribute syntax, as not all objects with have a '__dict__', and looking through '__dict__' will not search for attributes defined on the class or super classes or you object.

To address your other questions:
The code:
def initialize(context): Defines a new function object name 'initialize' that accepts one argument named 'context'.
When you say:

do the dot properties work like they would with a class?

remember that everything is an object, so saying:
initialize.atribute = 10 is completely legal.

There is nothing special about 'initialize' in python; however, this is the function that Quantopian will call with an empty Context object to set up your algorithm. The Context object there is basically a dictionary that allows you to index into it with attribute access notation. This means that:
context.attr == context['attr'] and that notation may be interchanged on the Context object.

To add attributes to an object, you must simply do:
myobject.newattribute = new_value This will only fail if 'myobject' is an instance of a class that defines a '__slots__' attribute, in which case, only the attributes named in that tuple will be allowed. In the general case, this is not defined, and instead a '__dict__' is defined implicitly so that users may add attributes as they wish.

Currently, there is no easy way to get a list of all the attributes of an object from within the Quantopian IDE; however, in a local python environment, you may use the builtin function 'dir' to return a list of strings naming all the attributes on an object. Hopefully someone will add this feature to the Quantopian IDE, it seems like it could be useful.

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 Paul,

Another concept which might be helpful is to think of context as a container that the Quantopian initialize() and handle_data() functions can mutually access. At a higher level (that we don't see in Quantopian), the context variable is shared between these two functions, and then you can pass it around to others that you define as well.

Besides all of the predefined attributes in context listed above helpfully, you can also define your own at will. Say, if you need an iterator, just put a context.i = 0 in your initialize, and then in handle_data, you can reference it as context.i to read/write, and so on.

Some good explanations from Joe up the for sure too. He certainly embraces python.
I'm still a bit in translation from other languages.

HTH too.

Thanks for the responses folks, it is definitely helping me understand!