• No results found

Uniqueness of Sets

2. Fundamentals of Python

2.5. Beyond the Lists

2.5.2. Uniqueness of Sets

The title of this Section reveals a widely spread and the most useful application of sets—from a group of elements return the gems. Sets are officially declared as the unordered collections of unique elements with a limited number of operations one can perform upon them. They differ from lists and tuples in a number of ways, with a basic syntax:

>>> s = {1} # alternatively: s = set([1])

>>> s {1}

>>> type(s)

<class 'set'>

where a new function of set has been used to convert the list.

collections.namedtuple Code 2.37

{ }, set

The first striking surprise is the behaviour:

>>> s = {3, -1j, 6, 'python', 4, 'quants'}

>>> s

{3, 4, 6, 'python', (-0-1j), 'quants'}

i.e. after providing the input, the order is rearranged. The second surprise comes when we try to extract any element from a set:

>>> s[1]

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: 'set' object does not support indexing

>>> s[1:3]

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: 'set' object is not subscriptable

revealing that neither indexing nor slicing for sets do not work.

Therefore, what is all that ado about sets? Well, as it has been said in the beginning, we are able to convert a collection of repeatable elements into a unique set, for instance:

>>> rvs = [random.randrange(20) for i in range(15)]

>>> rvs

[19, 8, 15, 9, 18, 8, 11, 9, 13, 14, 1, 17, 2, 11, 9]

>>> s = set(rvs)

>>> s

{1, 2, 8, 9, 11, 13, 14, 15, 17, 18, 19}

where all duplicates have been removed.

Having two different sets, we can perform certain operations upon them. Analyse the following examples:

>>> u1 = [random.randrange(20) for i in range(15)]

>>> u2 = [random.randrange(20) for i in range(15)]

>>> s1 = set(u1)

>>> s2 = set(u2)

>>> s1; s2

{0, 3, 5, 6, 7, 9, 11, 13, 14, 16, 17}

{2, 3, 4, 7, 9, 11, 13, 14, 18}

>>> s1.intersection(s2) # common elements {3, 7, 9, 11, 13, 14}

>>> s1.union(s2) # all elements of s1 and s2 together {0, 2, 3, 4, 5, 6, 7, 9, 11, 13, 14, 16, 17, 18}

>>> s1.difference(s2) # s1 - s2, or missing elements of {0, 16, 5, 6, 17} s1 in s2

>>> s2.difference(s1) # s2 - s1, or missing elements of {2, 18, 4} s2 in s1

Updating the set cannot be done by a simple addition, i.e.:

>>> {1, 2, 3} + {'a', '7'}

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: unsupported operand type(s) for +: 'set' and 'set'

however, with an aid of a special function, namely,

>>> s1

{0, 3, 5, 6, 7, 9, 11, 13, 14, 16, 17}

>>> s1.update({99, 100})

{0, 3, 99, 5, 6, 7, 100, 9, 11, 13, 14, 16, 17}

and the miracles can happen. What could be pretty useful is:

>>> s1

{0, 3, 5, 6, 7, 9, 11, 13, 14, 16, 17}

>>> s3 = {11, 13}

>>> s1.intersection_update(s3) {11, 13}

You may apply this method in order to update s1 set leaving it solely with those elements which have been common between s1 and a new set of s3.

For more information on other operations available for Python’s sets see, e.g.: https://docs.python.org/2/library/sets.html.

2.5.3. Dictionaries, i.e. Call Your Broker

The forth attractive form of storing and arranging the data are the Python’s dictionaries. The elements of the dictionaries enter the barn being labeled by key : value. Similarly to sets, the dictionaries are surround by curly brackets, and their keys are immutable.

Let’s introduce the fundamentals of dictionaries using an example of brokers’ details gathered together in one place (phonebook) where every one of them is described by name and phone number.

We start with:

>>> brokers = ["Lucky Luc", "Fat Joe", "Filthy Richard"]

>>> phones = [555432032, 555221891, 555988913]

>>> d = dict(zip(brokers, phones))

>>> d

{'Fat Joe': 555221891, 'Filthy Richard': 555988913, 'Lucky Luc': 555432032}

where, first, we zip both lists and next we create a dictionary with a help of the dict function. The key is given by the broker’s name while the corresponding value by his phone number. Adding a new broker’s detail we achieve thanks to:

>>> new = {"Johnny Cash" : 555443677}

>>> new

{'Johnny Cash': 555443677}

>>> d.update(new)

>>> d

{'Fat Joe': 555221891, 'Johnny Cash': 555443677, 'Filthy Richard': 555988913, 'Lucky Luc': 555432032}

therefore finding a phone number of Fat Joe in your phonebook is as easy as:

>>> d["Fat Joe"]

555221891 { }, dict()

Listing the names of your brokers or, alternatively, only all saved phone numbers in d requires:

>>> list(d.keys())

['Fat Joe', 'Johnny Cash', 'Filthy Richard', 'Lucky Luc']

>>> list(d.values())

[[555221891, 555443677, 555988913, 555432032]

Looking the broker’s name up follows:

>>> "Fat Joe" in d True

however

>>> 555443677 in d False

>>> 555443677 in d.values() True

Updating the key’s value is fairly straightforward, namely:

>>> new_phone_number = 555666777

>>> d["Fat Joe"] = new_phone_number

>>> d["Fat Joe"]

555666777

The application of Python’s dictionaries in quantitative finance or algorithmic trading is rather limited. However, you may find them practical if you fetch some data online and they are returned in a JSON file format as in the following case of the Google Finance query for the latest update on AAPL stock:

http://finance.google.com/finance/info?client=ig&q=AAPL:NASDAQ The body of the JSON file can be saved as a dictionary:

>>> stock = { "id": "22144" ,"t" : "AAPL" ,"e" : "NASDAQ" ,"l" : "117.75" ,"l_fix" : "117.75" ,"l_cur" : "117.75" ,"s":

"1" ,"ltt":"4:00PM EST" ,"lt" : "Nov 23, 4:00PM EST" ,

"lt_dts" : "2015-11-23T16:00:01Z" ,"c" : "-1.55" ,

"c_fix": "-1.55" , "cp" : "-1.30" ,"cp_fix" : "-1.30" ,

"ccol" : "chr" ,"pcls_fix" : "119.3" ,

"el": "117.18" ,"el_fix": "117.18" ,"el_cur": "117.16" ,

"elt" : "Nov 24, 7:31AM EST" ,"ec" : "-0.59" ,

"ec_fix" : "-0.59" ,"ecp" : "-0.50" ,

"ecp_fix" : "-0.50" ,"eccol" : "chr" ,

"div" : "0.52" ,"yld" : "1.77" }

which corresponds to the information provided online, i.e.:

Having that, the last close-price of Apple Inc. and the most current price of the stock in pre-market can be extracted by:

>>> stock["l"]

'117.75'

>>> stock["el"]

'117.18'

respectively. More on hacking Google Finance for algo traders see:

http://www.quantatrisk.com/2015/05/07/hacking-google-finance-in-pre-market-trading-python/.

If you find the Python’s dictionaries particularly appealing in your research or for the projects, please visit https://docs.python.org/

3.5/library/stdtypes.html#dict to learn more.

2.6. Functions

One of the coolest thing people love about Python is its flexibility in defining and creating functions. Those of you who are more familiarised with other languages like Fortran or C++ remember how much pain it causes to make sure that a function is of a specific type and it returns a right result. There exists a certain trade-off between the final speed of the code execution and the time dedicated to doubly verify that all has been written correctly.

The simplest Python syntax that defines a custom function, i.e. the function that you write on your own (or your girlfriend sitting on your laps). I introduced the term custom in this book in order to mark a distinction among functions available to us in the standard version of Python or provided by the third-party modules, and the ones you compose from a scratch.

A void function would take a form of:

def donothing():

return

donothing()

that does absolutely nothing while called. We define a function by typing a keyword def first, followed by the function’s name (best to use lowercase with/out underscore token) and with double round brackets empty inside (if no parameters/arguments are specified or required to be passed on).

A good style of writing a code in Python suggests to keep double blank lines between the function(s) and/or the rest of the main program. This rule can be neglected but it makes all future Python codes easily readable and understoodable worldwide. Therefore, learn now how to keep your style at the highest level.

Every function which does not return any output is not asked be ended with a return keyword, e.g.

def donothing():

x = 1 donothing()

or

def justprint():

print("_"*20)

print("Name and Date") justprint()

____________________

Name and Date def, return