Lime


In [86]:
%matplotlib inline
from lime import lime


---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-86-8abd7ac3caf9> in <module>()
----> 1 get_ipython().magic(u'matplotlib inline')
      2 from lime import lime

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in magic(self, arg_s)
   2203         magic_name, _, magic_arg_s = arg_s.partition(' ')
   2204         magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2205         return self.run_line_magic(magic_name, magic_arg_s)
   2206 
   2207     #-------------------------------------------------------------------------

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in run_line_magic(self, magic_name, line)
   2124                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
   2125             with self.builtin_trap:
-> 2126                 result = fn(*args,**kwargs)
   2127             return result
   2128 

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/magics/pylab.pyc in matplotlib(self, line)

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/magic.pyc in <lambda>(f, *a, **k)
    191     # but it's overkill for just that one bit of state.
    192     def magic_deco(arg):
--> 193         call = lambda f, *a, **k: f(*a, **k)
    194 
    195         if callable(arg):

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/magics/pylab.pyc in matplotlib(self, line)
     78         """
     79         args = magic_arguments.parse_argstring(self.matplotlib, line)
---> 80         gui, backend = self.shell.enable_matplotlib(args.gui)
     81         self._show_matplotlib_backend(args.gui, backend)
     82 

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in enable_matplotlib(self, gui)
   2929         """
   2930         from IPython.core import pylabtools as pt
-> 2931         gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
   2932 
   2933         if gui != 'inline':

/Users/administrator/dev/lime/env/lib/python2.7/site-packages/IPython/core/pylabtools.pyc in find_gui_and_backend(gui, gui_select)
    250     """
    251 
--> 252     import matplotlib
    253 
    254     if gui and gui != 'auto':

ImportError: No module named matplotlib

In [44]:
from datetime import timedelta


class LimeInvalidTicker(Exception):
    '''
    An Exception for handling invalid tickers
    '''

    def __init__(self):
        self.msg = ('Lime was not able to find that ticker symbol on Netfonds.'
                    'Please check your ticker and try again.')

    def __str__(self):
        return repr(self.msg)


class LimeInvalidQuery(Exception):
    '''
    An Exception for handling invalid requests

    ###Parameters
    * url -- string, should be self._url used to access NetFonds
    '''

    def __init__(self, url):
        self.url = url
        self.msg = ('Lime was not able to contact Netfonds, based'
                    ' on the information you provided.'
                    'Please check your request and try again.')

    def __str__(self):
        return repr("Invalid Query:{}:\n{}".format(self.msg, self.url))


class LimeInvalidDate(Exception):
    '''
    An Exception for handling invalid dates for requests Invalid

    ###Parameters
    * start -- datetime object, should be self.start_date
    * end -- datetime object, should be self.end_date

    '''

    def __init__(self, start, end):
        self.msg = self.check_date(start, end)
        self.start = start
        self.end = end

    def check_date(self):
        '''
        returns the appropriate error message based
        on the provided dates.
        '''
        if (self.end - self.start) > timedelta(21):
            self.msg = ('Date range is greater than 21 days.'
                        'Data does not exist on NetFonds beyond 21 days.\n'
                        'Please reconstruct your query and try again.')
        if self.start > self.end:
            self.msg = ('The Start Date is greater than the End Date.\n'
                        'You most likely reversed the begining_date and end_date.')

    def __str__(self):
        return repr("Invalid Date:{}:\n{}".format(self.msg, self.date))

In [ ]:
import datetime
from datetime import timedelta
from pandas import DataFrame, concat, date_range, read_csv

from .exceptions import LimeInvalidQuery, LimeInvalidDate, LimeInvalidTicker


class Lime:
    '''
    A simple API for extracting stock tick data.

    ###Parameters
    * start_date -- datetime, date beginning the retrieval window
    * end_date -- datetime, date ending the retrieval window
    * exchange -- string ( optional ), ticker's exchange: ['Nasdaq', 'Nyse', 'Amex']
    * ticker -- string ( optional ), stock ticker symbol. With or with out
        Netfonds exchange extension.
    '''
    def __init__(self, start_date, end_date=None, exchange=None, ticker=None):
        self.start_date = self.initialize_date(start_date)
        self.end_date = self.initialize_date(end_date)
        self.ticker = None
        self._exchange = exchange
        self._file_format = 'csv'
        self._df = None
        self._exchanges = {
            'Nasdaq': '.O',
            'Nyse': '.N',
            'Amex': '.A'
        }
        self.exchange_extensions = ['O', 'N', 'A']
        self._url = 'http://www.netfonds.no/quotes/tradedump.php'
        self.uri = None
        
    def get_exchange(self):
        ''' Returns the exchange chosen '''
        return self._exchange

    def get_df(self):
        ''' Gets the stored tick data '''
        return self._df

    def set_df(self, dataframe):
        '''
        Sets stored tick data
        
        Parameters
        * dataframe -- pandas.DataFrame()
        '''
        self._df = concat([self.get_df(), dataframe]) if self._df is None else dataframe
        self.process_data()

    def initialize_date(self, date):
        '''
        Returns parsed todays date, a parsed supplied date

        ###Parameters
        * date -- datetime, date to be parsed
        '''
        if not date:
            date = datetime.date.today()
        return self.date_parse(date)

    def date_parse(self, date):
        '''
        Parses date to YYYY/MM/DD.

        ###Parameters
        * date -- datetime, date to be parsed
        '''
        return date.strftime('%Y%m%d')

    def check_date(self, start, end):
        '''
        Checks whether supplied dates are acceptable.

        ###Parameters
        * start -- datetime, date beginning the retrieval window
        * end -- datetime, date ending the retrieval window
        '''
        if timedelta(0) > (end - start) > timedelta(21):
            raise LimeInvalidDate(start, end)
        return True

    def format_ticker_with_exchange_extenstion(self):
        self.ticker = "{}{}".format(self.ticker,
                                    self._exchanges[self._exchange.title()])
        return self.ticker

    def validate_ticker_exchange_extenstion(self):
        '''Checks if ticker has a valid exchange extension. '''
        extension = self.ticker.split('.')[1]
        if extension in self.exchange_extensions:
            return True
        return False

    def check_ticker_exchange_extenstion(self):
        '''
        Check's whether the appropriate netfonds extension, ( '.N', '.O', '.A' ), has been added.
        If it hasn't, but the ticker's exchange has, it adds the appropriate extension.
        If neither have; it raises a LimeInvalidTicker exception.
        '''
        try:
            self.validate_ticker_exchange_extenstion()
        except IndexError:
            if not self._exchange:
                self.get_exchange_extension_from_ticker()
            self.format_ticker_with_exchange_extenstion()
        else:
            raise LimeInvalidTicker()
        
        return self.ticker

    def get_exchange_extension_from_ticker(self):
        '''
        Loops through the three exchanges Netfonds supports, ( Nasdaq, NYSE, Amex),
        and returns the correct exchange extension if it exists.
        '''
        for key in self._exchanges.keys():
            self.ticker = "{}{}".format(self.ticker, self._exchanges[key])
            self._get_tick_data()
            if self._df is not None and (len(self._df.columns) > 1):
                self._exchange = key
                self.format_ticker_with_exchange_extenstion()
                return self._exchange

        raise LimeInvalidTicker()

    def set_start_end_dates(self, start, end=None):
        '''
        Parses and Prepares Start and End dates.

        ###Parameters
        * start -- datetime
        * end -- ( optional ) datetime, defaults to today's date
        '''
        self.start_date = self.date_parse(start)
        self.end_date = self.date_parse(end) if end else self.get_date_today()
        self.check_date(start, end)
    
    def process_data(self):
        '''
        Cleans data after its retrieved from Netfonds
        '''
        df = self.get_df()
        try:
            df.time = df.time.apply(lambda x: datetime.datetime.strptime(x, '%Y%m%dT%H%M%S'))
            df = df.set_index(df.time)
        except AttributeError:
            raise LimeInvalidQuery(self.uri)
   
    def _get_tick_data(self):
        '''
        Retrieves tick data from Netfonds from a known ticker.
        '''
        self.uri = '{}?date={}&paper={}&csv_format={}'.format(self._url,
                                                              self.start_date,
                                                              self.ticker,
                                                              self._file_format)

        self.set_df(read_csv(self.uri))

    def get_trades(self, ticker, exchange=None):
        '''
        Gets the trades made for a ticker on a specified day.

        ###Parameters
        * ticker -- string, stock ticker symbol
        '''
        if exchange:
            self.exchange = exchange
            
        self.ticker = ticker
        self.check_ticker_exchange_extenstion()
        self._get_tick_data()
        
        return self.get_df()
    
    def get_trade_history(self, ticker, start_date, end_date=None):
        '''
        Retrieves the trades made for a ticker from a range of days.

        ###Parameters
        * ticker -- string, stock ticker symbol
        * start_date -- datetime, starting date of retrieval window
        * end_date  -- datetime (optional), ending date of retrieval window.
            defaults to today, if committed.

        Note: Tick data only persist for 21 days on Netfonds. Any queries greater
        than that window will raise a LimeInvalidQuery exception.
        '''
        self.ticker = ticker
        self.set_start_end_dates(start_date, end_date)

        for day in date_range(start=start_date, end=self.end_date, freq='B'):
            self.start_date = self.date_parse(day)
            self.set_df(self.get_trades(self.ticker))

        return self.get_df()

In [79]:
start_date = datetime.datetime.today() - timedelta(days=5)

In [80]:
lime = Lime(start_date, exchange="Nasdaq")

In [83]:
AAPL_single_day = lime.get_trades('AAPL')

In [84]:
AAPL_single_day


Out[84]:
time price quantity board source buyer seller initiator
0 2014-10-06 15:30:00 99.9500 100 NaN Auto trade NaN NaN NaN
1 2014-10-06 15:30:00 99.9600 100 NaN Auto trade NaN NaN NaN
2 2014-10-06 15:30:00 99.9700 428 NaN Auto trade NaN NaN NaN
3 2014-10-06 15:30:00 99.9500 100 NaN Auto trade NaN NaN NaN
4 2014-10-06 15:30:00 99.9550 205 NaN Auto trade NaN NaN NaN
5 2014-10-06 15:30:00 99.9600 100 NaN Auto trade NaN NaN NaN
6 2014-10-06 15:30:00 99.9400 248807 NaN Auto trade NaN NaN NaN
7 2014-10-06 15:30:00 99.9500 100 NaN Auto trade NaN NaN NaN
8 2014-10-06 15:30:00 99.9600 100 NaN Auto trade NaN NaN NaN
9 2014-10-06 15:30:00 99.9500 100 NaN Auto trade NaN NaN NaN
10 2014-10-06 15:30:00 99.9600 100 NaN Auto trade NaN NaN NaN
11 2014-10-06 15:30:00 99.9500 100 NaN Auto trade NaN NaN NaN
12 2014-10-06 15:30:00 99.9600 100 NaN Auto trade NaN NaN NaN
13 2014-10-06 15:30:00 99.9500 100 NaN Auto trade NaN NaN NaN
14 2014-10-06 15:30:01 99.9500 500 NaN Auto trade NaN NaN NaN
15 2014-10-06 15:30:01 99.9550 100 NaN Auto trade NaN NaN NaN
16 2014-10-06 15:30:01 99.9500 100 NaN Auto trade NaN NaN NaN
17 2014-10-06 15:30:01 99.9600 100 NaN Auto trade NaN NaN NaN
18 2014-10-06 15:30:01 99.9687 1400 NaN Auto trade NaN NaN NaN
19 2014-10-06 15:30:01 99.9600 100 NaN Auto trade NaN NaN NaN
20 2014-10-06 15:30:01 99.9500 100 NaN Auto trade NaN NaN NaN
21 2014-10-06 15:30:01 99.9600 100 NaN Auto trade NaN NaN NaN
22 2014-10-06 15:30:01 99.9500 100 NaN Auto trade NaN NaN NaN
23 2014-10-06 15:30:01 99.9600 100 NaN Auto trade NaN NaN NaN
24 2014-10-06 15:30:01 99.9500 100 NaN Auto trade NaN NaN NaN
25 2014-10-06 15:30:01 99.9600 2000 NaN Auto trade NaN NaN NaN
26 2014-10-06 15:30:01 99.9500 200 NaN Auto trade NaN NaN NaN
27 2014-10-06 15:30:01 99.9400 300 NaN Auto trade NaN NaN NaN
28 2014-10-06 15:30:01 99.9500 200 NaN Auto trade NaN NaN NaN
29 2014-10-06 15:30:01 99.9600 200 NaN Auto trade NaN NaN NaN
... ... ... ... ... ... ... ... ...
44863 2014-10-06 21:59:57 99.6500 187 NaN Auto trade NaN NaN NaN
44864 2014-10-06 21:59:57 99.6400 413 NaN Auto trade NaN NaN NaN
44865 2014-10-06 21:59:57 99.6500 100 NaN Auto trade NaN NaN NaN
44866 2014-10-06 21:59:57 99.6361 179 NaN Auto trade NaN NaN NaN
44867 2014-10-06 21:59:57 99.6500 300 NaN Auto trade NaN NaN NaN
44868 2014-10-06 21:59:57 99.6499 778 NaN Auto trade NaN NaN NaN
44869 2014-10-06 21:59:57 99.6500 120 NaN Auto trade NaN NaN NaN
44870 2014-10-06 21:59:58 99.6500 3561 NaN Auto trade NaN NaN NaN
44871 2014-10-06 21:59:58 99.6200 400 NaN Auto trade NaN NaN NaN
44872 2014-10-06 21:59:58 99.6500 700 NaN Auto trade NaN NaN NaN
44873 2014-10-06 21:59:58 99.6499 600 NaN Auto trade NaN NaN NaN
44874 2014-10-06 21:59:58 99.6451 700 NaN Auto trade NaN NaN NaN
44875 2014-10-06 21:59:58 99.6500 200 NaN Auto trade NaN NaN NaN
44876 2014-10-06 21:59:58 99.6400 100 NaN Auto trade NaN NaN NaN
44877 2014-10-06 21:59:58 99.6500 703 NaN Auto trade NaN NaN NaN
44878 2014-10-06 21:59:58 99.6400 400 NaN Auto trade NaN NaN NaN
44879 2014-10-06 21:59:58 99.6500 540 NaN Auto trade NaN NaN NaN
44880 2014-10-06 21:59:59 99.6500 2937 NaN Auto trade NaN NaN NaN
44881 2014-10-06 21:59:59 99.6499 5700 NaN Auto trade NaN NaN NaN
44882 2014-10-06 21:59:59 99.6400 100 NaN Auto trade NaN NaN NaN
44883 2014-10-06 21:59:59 99.6500 180 NaN Auto trade NaN NaN NaN
44884 2014-10-06 21:59:59 99.6400 100 NaN Auto trade NaN NaN NaN
44885 2014-10-06 21:59:59 99.6300 100 NaN Auto trade NaN NaN NaN
44886 2014-10-06 21:59:59 99.6400 400 NaN Auto trade NaN NaN NaN
44887 2014-10-06 21:59:59 99.6300 100 NaN Auto trade NaN NaN NaN
44888 2014-10-06 21:59:59 99.6200 100 NaN Auto trade NaN NaN NaN
44889 2014-10-06 22:00:00 99.6200 794 NaN Auto trade NaN NaN NaN
44890 2014-10-06 22:00:00 99.6250 400 NaN Auto trade NaN NaN NaN
44891 2014-10-06 22:00:00 99.6200 866345 NaN Auto trade NaN NaN NaN
44892 2014-10-06 22:00:04 99.6200 800 NaN Auto trade NaN NaN NaN

44893 rows × 8 columns


In [85]:
fig = plt.figure(figsize(18,4), dpi=1600)
AAPL_single_day.price.plot()
plt.title("Apple stock movements on: " + str(lime.start_date))


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-85-1fe5304ed581> in <module>()
----> 1 fig = plt.figure(figsize(18,4), dpi=1600)
      2 AAPL_single_day.price.plot()
      3 plt.title("Apple stock movements on: " + str(lime.start_date))

NameError: name 'plt' is not defined

In [5]:
AAPL_many_days = lime.get_many(begining_date=datetime.date(2013,5,29), end_date=datetime.date(2013,6,18), ticker='AAPL')

In [6]:
AAPL_many_days


Out[6]:
&ltclass 'pandas.core.frame.DataFrame'>
DatetimeIndex: 42094 entries, 2013-05-29 15:30:00 to 2013-05-29 22:00:01
Data columns (total 8 columns):
time         42094  non-null values
price        42094  non-null values
quantity     42094  non-null values
board        0  non-null values
source       42094  non-null values
buyer        0  non-null values
seller       0  non-null values
initiator    0  non-null values
dtypes: datetime64[ns](1), float64(5), int64(1), object(1)

In [53]:
fig = plt.figure(figsize(18,4), dpi=1600)
AAPL_many_days.price.plot()
plt.title('Apple price movements over the last 21 days')
savefig('Apple.png', bbox_inches=0)



In [7]:
goog = lime.get_many(begining_date=datetime.date(2013,5,29), end_date=datetime.date(2013,6,18), ticker='GOOG')

In [52]:
fig = plt.figure(figsize(18,4), dpi=1600)
goog.price.plot()
plt.title("Google's price movements over the last 21 days")
savefig('GOOG.png', bbox_inches=0)



In [20]:
import pandas
#df = pandas.merge(AAPL_many_days, goog, on='time', suffixes=('_AAPL', '_GOOG'))
plt.figure(figsize(18,8), dpi=1600)
plt.subplot(212)
df.price_AAPL.plot()
legend(loc='best')

plt.subplot(211)
df.price_GOOG.plot(color='g')
plt.title("Apple's and Google's price movements"); legend(loc='best')


Out[20]:
<matplotlib.legend.Legend at 0xe7b26d8>

Version Control:


In [48]:
!git add lime_demo.ipynb

In [50]:
!git commit


[master 7040744] updated with date index parsing
 1 file changed, 333 insertions(+), 322 deletions(-)
 rewrite lime_demo.ipynb (91%)

In [ ]: