Files
catalyst/zipline/gens/tradegens.py
T

164 lines
5.0 KiB
Python

"""
Tools to generate trade events without a backing store. Useful for testing
and zipline development
"""
import random
import pytz
from itertools import chain, cycle, ifilter, izip
from datetime import datetime, timedelta
from zipline.gens.utils import hash_args, create_trade
def date_gen(start = datetime(2006, 6, 6, 12, tzinfo=pytz.utc),
delta = timedelta(minutes = 1),
count = 100):
"""
Utility to generate a stream of dates.
"""
return (start + (i * delta) for i in xrange(count))
def mock_prices(count, rand = False):
"""
Utility to generate a stream of mock prices. By default
cycles through values from 0.0 to 10.0, n times. Optional
flag to give random values between 0.0 and 10.0
"""
if rand:
return (random.uniform(1.0, 10.0) for i in xrange(count))
else:
return (float(i % 10) + 1.0 for i in xrange(count))
def mock_volumes(count, rand = False):
"""
Utility to generate a set of volumes. By default cycles
through values from 100 to 1000, incrementing by 50. Optional
flag to give random values between 100 and 1000.
"""
if rand:
return (random.randrange(100, 1000) for i in xrange(count))
else:
return ((i * 50)%900 + 100 for i in xrange(count))
def fuzzy_dates(count = 500):
"""
Add +-10 seconds to each event from a date_gen. Note that this
still guarantees sorting, since the default on date_gen is minute
separation of events.
"""
for date in date_gen(count = count):
yield date + timedelta(seconds = random.randint(-10, 10))
class SpecificEquityTrades(object):
"""
Yields all events in event_list that match the given sid_filter.
If no event_list is specified, generates an internal stream of events
to filter. Returns all events if filter is None.
Configuration options:
count : integer representing number of trades
sids : list of values representing simulated internal sids
start : start date
delta : timedelta between internal events
filter : filter to remove the sids
"""
def __init__(self, *args, **kwargs):
# We shouldn't get any positional arguments.
assert len(args) == 0
# Unpack config dictionary with default values.
self.count = kwargs.get('count', 500)
self.sids = kwargs.get('sids', [1, 2])
self.start = kwargs.get('start', datetime(2008, 6, 6, 15, tzinfo = pytz.utc))
self.delta = kwargs.get('delta', timedelta(minutes = 1))
# Default to None for event_list and filter.
self.event_list = kwargs.get('event_list')
self.filter = kwargs.get('filter')
# Hash_value for downstream sorting.
self.arg_string = hash_args(*args, **kwargs)
self.generator = self.create_fresh_generator()
def __iter__(self):
return self
def next(self):
return self.generator.next()
def rewind(self):
self.generator = self.create_fresh_generator()
def get_hash(self):
return self.__class__.__name__ + "-" + self.arg_string
def create_fresh_generator(self):
if self.event_list:
unfiltered = (event for event in self.event_list)
# Set up iterators for each expected field.
else:
dates = date_gen(count=self.count,
start=self.start,
delta=self.delta
)
prices = mock_prices(self.count)
volumes = mock_volumes(self.count)
sids = cycle(self.sids)
# Combine the iterators into a single iterator of arguments
arg_gen = izip(sids, prices, volumes, dates)
# Convert argument packages into events.
unfiltered = (create_trade(*args, source_id = self.get_hash())
for args in arg_gen)
# If we specified a sid filter, filter out elements that don't
# match the filter.
if self.filter:
filtered = ifilter(lambda event: event.sid in self.filter, unfiltered)
# Otherwise just use all events.
else:
filtered = unfiltered
# Return the filtered event stream.
return filtered
# !!!!!!! Deprecated for now !!!!!!!!!
def RandomEquityTrades(object):
def __init__(self):
# We shouldn't get any positional args.
assert args == ()
self.count = config.get('count', 500)
self.sids = config.get('sids', [1,2])
self.filter = config.get('filter')
dates = fuzzy_dates(count)
prices = mock_prices(count, rand = True)
volumes = mock_volumes(count, rand = True)
sids = cycle(sids)
arg_gen = izip(sids, prices, volumes, dates)
unfiltered = (create_trade(*args) for args in arg_gen)
if filter:
filtered = ifilter(lambda event: event.sid in filter, unfiltered)
else:
filtered = unfiltered
return filtered
# if __name__ == "__main__":
# import nose.tools; nose.tools.set_trace()
# trades = SpecificEquityTrades(filter = [1])