Commit Graph

140 Commits

Author SHA1 Message Date
Jean Bredeche 02ded435f6 DEV: Don't log an error if we can't find a matching asset/field/day triple in fetcher data 2016-04-25 09:47:18 -04:00
Eddie Hebert 66d05aa563 PERF: Improve read time for smaller num of assets.
The BcolzDailyBarReader was optimized for the pipeline case of reading
all assets at once.

Now that the reader is also used to support daily history the case of
reading a data for a small number of assets is more common, particularly
in algorithms that use the history API which have a high rotation of
assets (e.g. an algorithm which pipeline uses to set the active
universe)

Remove the bottleneck in reading a small number of assets by
conditionally reading the slice for each asset from the carray, instead
of reading the data for all equities and then indexing into that full
array. On a certain number of assets, it is still better to read all the
data at once. On the Quantopian dataset, which holds data for 20000
about for the last 10 years of equity data (where not all equities trade
over the full range), stored in 118 blosc blp files per column, the
tipping point where the 'read all' mode wins out between 3000-4000
assets.

That number was tested by trying to exercise a worst case scenario where
the equities were spread out evenly across the blp files, by stepping
along a sorted list of assets that were alive over a query range which
spanned 70 trading days.
```
size = 3000
sids = [assets[i] for i in range(0, len(assets), len(assets) /
size)][:size]
```

Also, add parameter to WithBcolzDailyBarReader fixture which allows the
test to specify what the threshold count for reading all data should be,
so that the test_us_equity_pricing can be forced into either mode to
make sure that both branches in logic are covered by all test cases.

On local dev machine this patch improves the read time of `load_raw_array`
for one asset from 100 ms to 96.5 µs. (10^5 improvement.) With reading
only asset per call a being an observed common case when populating the
non-cached values in USEquityHistoryLoader.
2016-04-21 20:43:52 -04:00
Jean Bredeche 9d1e15ddde BUG: Fetcher wasn't working properly in before_trading_start.
We were trying to use the previous day in before_trading_start because
we were looking for the previous market minute, then normalizing it.  That's
no longer the case, as we want to use today's date for fetcher lookups
in before_trading_start.

Also refactored a bit how dataportal determines if a query should be
routed to the fetcher data structures.
2016-04-21 15:09:14 -04:00
Jean Bredeche 5d3dcc3df4 PERF: do work later, when needed. 2016-04-16 21:39:55 -04:00
Joe Jevnik bc0b117dc9 MAINT: make the data loading apis more consistent.
Changes BcolzDailyBarWriter to not be an abc, data is passed as an
iterator of (sid, dataframe) pairs to the write method.

Changes the AssetsDBWriter to be a single class which accepts an engine
at construction time and has a `write` method for writing dataframes for
the various tables. We no longer support writing the various other data
types, callers should coerce their data into a dataframe themselves. See
zipline.assets.synthetic for some helpers to do this.

Adds many new fixtures and updates some existing fixtures to use the new
ones:

WithDefaultDateBounds
  A fixture that provides the suite a START_DATE and END_DATE. This is
  meant to make it easy for other fixtures to synchronize their date
  ranges without depending on eachother in strange ways. For example,
  WithBcolzMinuteBarReader and WithBcolzDailyBarReader by default should
  both have data for the same dates, so they may use depend on
  WithDefaultDates without forcing a dependency between them.

WithTmpDir, WithInstanceTmpDir
  Provides the suite or individual test case a temporary directory.

WithBcolzDailyBarReader
  Provides the suite a BcolzDailyBarReader which reads from bcolz data
  written to a temporary directory. The data will be read from
  dataframes and then converted to bcolz files with
  BcolzDailyBarWriter.write

WithBcolzDailyBarReaderFromCSVs
  Provides the suite a BcolzDailyBarReader which reads from bcolz data
  written to a temporary directory. The data will be read from a
  collection of CSV files and then converted into the bcolz data through
  BcolzDailyBarWriter.write_csvs

WithBcolzMinuteBarReader
  Provides the suite a BcolzMinuteBarReader which reads from bcolz data
  written to a temporary directory. The data will be read from
  dataframes and then converted to bcolz files with
  BcolzMinuteBarWriter.write

WithAdjustmentReader
  Provides the suite a SQLiteAdjustmentReader which reads from an in
  memory sqlite database. The data will be read from dataframes and then
  converted into sqlite with SQLiteAdjustmentWriter.write

WithDataPortal
  Provides each test case a DataPortal object with data from temporary
  resources.
2016-04-15 23:46:10 -04:00
Eddie Hebert 5f9d0a148d BUG: Prevent out of order history arrays.
Fix a bug where if history were called with assets `[1, 2]` and then
subsequently, `[2, 1]`, the loader would return the cached array in
order for `[1, 2]`.

Instead cache an AdjustedArray for each asset, then when a history
window is requested, check if each asset has a sufficient cache, and if
not then read values for the assets which are missing or need to be
refreshed.

An added benefit of this change is that if a subsequent call to history
has a smaller number of assets than the previous, no new data needs to
be read from disk. e.g. a call with assets `[1, 2, 3]` and then `[1, 2]`
would use the cached values for `1` and `2` from the first call.

Conversely, if the second call has more assets, then only the data for
the new assets needs to be retrieved. e.g. a history with `[1, 2]`, then
`[1, 2, 3]` would only need (assuming `1` and `2` have not expired) to
retrieve data for `3`. Unfortunately, the benefit here is not great
because `load_raw_arrays` is optimized for reading many assets, and
pulls the entire daily bar dataset into memory. This change makes tuning
`load_raw_arrays` so that faster reads (e.g. by slicing from the carray
for each asset, instead of pulling all data into a numpy array), when
only a few assets are requested, more beneficial than it would have been
previously.
2016-04-15 22:44:00 -04:00
Eddie Hebert e1b376a49b BUG: Add limit to memory growth on sliding windows
Add a cap of 5 sliding windows (one per OHCLV column) to the history
loader's cache of sliding windos.

This prevents unbounded growth on algorithms that call history with a
highly varied list of equities.

To follow is splitting the cache up by column and by sid, so that the
loader does not re-prefetch sids which have already been read with
sufficient data; however this patch is enough to fix the issue where an
algo with high rotation can add up a megabyte per day of memory on
algorithms which rotate on a 5% dollar volume pipeline. With this cap
those algorithms have more plateaus with regard to memory consumption.

This patch requires new dependency of `cachetools` library.
2016-04-14 22:20:02 -04:00
Eddie Hebert e78f4f0729 PERF: Remove memoization from minute bar position.
Instead of using the `remember_last` memoization on all calls to
`_find_position_of_minute`, add an instance local cache which is only
used by the `get_value` call. The `get_value` call is very hot, so any
extra overhead (e.g. creating the WeakArgs on every invocation) becomes
costly. The current usage `get_value` also has the property that it is
called with monotonically increasing, but with a high repeat count on
each value. (A further improvement could making a `get_value` which
supports being used by many sids, for use by the update portfolio
positions.)

The caching is not done at the `_find_position_of_minute_level` because
`unadjusted_window` always uses two positions on the tape (start and end
of range) which would cause the entries and removal into the cache which
would be invalidated both between the calls of start and end, and next
call of the function.
2016-04-14 10:08:35 -04:00
Eddie Hebert 0a3c9c8448 MAINT: Remove adjusted arg to position of minute.
The argument was only needed for mapping the positions which need to be
removed on adjusted windows. The start and end position of each range
can be derived from the early closes' positions and the market open,
respectively.

Remove to reduce moving parts.
2016-04-14 09:56:48 -04:00
Jean Bredeche 3a1bcdbc39 Merge pull request #1117 from quantopian/error_messages2
FIX: Check types of args passed to api methods on data
2016-04-13 20:38:41 -04:00
Eddie Hebert 5ea0bd2f87 PERF: Remove extra daily history caching.
The cache in data portal was added before the change to using a
CachedObject to wrap the window_blocks in the USEquityHistoryLoader.

Removing this extra layer saves some cycles.

Does not fix current memory investigaton (since only one sids/dts pair
per column was cached in `_equity_daily_reader_array_data` at a time),
but removing should make it more clear where needed references are being
held.
2016-04-13 11:11:00 -04:00
Andrew Liang 2775cc7ca4 FIX: Remove support for passing in sid int in place of Asset 2016-04-13 09:47:07 -04:00
Eddie Hebert d659a1d78c BUG/PERF: Remove extra minute bar loader cache.
The minute history loader caching was incorrectly mimicking the daily
history loader caching.

Where caching the adjusted array on the last dt helps an access pattern
of repeated calling history windows on the same day (which has an end_dt
of the previous day), with minute windows the end dt is always moving
forward, so the cached values are seldom used. (Would only be used if
`history` was called with same parameters twice on the same simulation time.)
2016-04-12 21:27:34 -04:00
Richard Frank 35085c6040 MAINT: Removed unused method 2016-04-12 19:33:22 -04:00
Richard Frank 5254b273b2 PERF: Reimplemented remember_last with a weak_lru_cache
which won't leak instances whose methods have been decorated

(specifically DataPortal instances)

MAINT: Not using functools32 anymore
2016-04-12 19:33:21 -04:00
Richard Frank 32a400a9fb BUG: Fixing bitness issues on 32-bit systems
by being explicit with sizes
2016-04-12 17:07:50 -04:00
Eddie Hebert 8313c8c36c Merge pull request #1125 from quantopian/enforce-sorted-on-minute-bars
BUG: Enforce sorted order on minutes to delete.
2016-04-12 15:18:30 -04:00
Eddie Hebert d27f85e16b BUG: Enforce sorted order on minutes to delete.
The intervals are returned as a set, so order is not guaranteed,
which becomes exposed when reading windows which span multiple years.

The deletion of values from the regular sized minute array assumes that
intervals can be reversed to delete the array from the back.
2016-04-12 14:16:10 -04:00
Jean Bredeche f6902f0368 BUG: bar_data.history too limiting on iterable types
In before_trading_start, history needs to call
DataPortal.get_adjustments, and that method wasn’t correctly checking
for iterables.
2016-04-11 14:02:27 -04:00
Eddie Hebert ccef816e7e MAINT: Remove unused member.
The "in before trading start logic" is now all handled inside of
`BarData`.
2016-04-11 13:47:17 -04:00
Eddie Hebert 0a3a2f3653 BUG: Ensure matched input length to minute writer.
When the dts and length of cols are mismatched the writer behaves in
unintended ways. e.g. in a case where a consumer passed dts which had
minutes with no trades removed, but regular (market minute for day)
sized arrays for the data with `0`'s on minutes without trades, the non
trade minutes from cols are written to slots in the output where a trade
is intended.

Protect against this misuse by checking that all lengths are equal when
using the `write_cols` method.

Make a separate `_write_cols` method for use by both `write_cols` and
`write`, since the `write` method which takes a DataFrame has the
matched input length enforced by the DataFrame.
2016-04-07 13:53:59 -04:00
Eddie Hebert 16fd6681a6 ENH: Rewrite of Zipline to use lazy access pattern
More documentation to follow in release notes.

Based on lazy-mainline branch, see for more details.

Also-By: Jean Bredeche <jean@quantopian.com>
Also-By: Andrew Liang <aliang@quantopian.com>
Also-By: Abhijeet Kalyan <akalyan@quantopian.com>
2016-04-04 16:12:58 -04:00
Eddie Hebert be08a77d76 BUG: Prevent writing int max instead of nan.
np.array.astype can not be relied upon to convert nan's reliably to 0

Fix by calling nan_to_num on the float arrays before converting to
uint32.
2016-03-30 14:35:06 -04:00
Eddie Hebert 75213ac176 MAINT: Write open and closes for minute bar format
Write arrays representing corresponding market opens and market closes,
which will eventually replace the `minute_index` field.

The market closes are being added for incoming work on another branch
which will use the market closes to generate a list of non-market
minutes to filter out when returning data from `unadjusted_window`.
2016-03-24 23:18:42 -04:00
Richard Frank d873038a7e BUG: Specify int64 instead of system int
to handle 32bit python
2016-03-23 15:26:52 -04:00
Eddie Hebert 0f14972e08 ENH: Unadjusted window data for minute bars.
Add a method to minute bar reader which returns the OHLCV for all
requested fields for a list assets over the specified start and end
minutes.

Initial usage is intended for use by a loader which consumes minute bar
data to resample into daily bars, but may also be used when aggregating
minute data during '1d' history calls in Q2.0.

This iteration does not include including of early closes.
2016-03-14 21:52:01 -04:00
Eddie Hebert 37d341bb95 BUG: Truncate treasury curves to env min date. 2016-03-08 17:14:28 -05:00
Joe Jevnik 5eb453675d BUG: don't fail if you cannot make a webrequest 2016-02-11 18:46:43 -05:00
Scott Sanderson 5f49fa22cb MAINT: Upgrade numpy and fix warnings.
Mostly fixes ambiguous calls to numpy.full, and uses explicitly-united
NaT values.
2016-02-11 18:46:39 -05:00
Eddie Hebert 27f94f83fa ENH: Allow passing of numpy arrays to writer.
For faster parsing and writing workflows, do not require a DataFrame.
2016-02-02 14:03:42 -05:00
Eddie Hebert 488721e805 ENH: Add padding method to minute bars writer.
So that consumers can write empty days worth of data, without needing
to construct a DataFrame with zero data force a write.

The internal loader uses `last_date_in_output_for_sid` to signify that
data has been attempted to be retrieved for all dates up until that, so
that when resuming a job those retrieval of data for those dates are not
re-attempted.

Also, used to make the write logic cleaneer, by making it only
necessary to create an array large enough for the given df.
2016-02-01 14:18:22 -05:00
Jeremiah Lowin e44c0d42e1 Replace print with logger.info 2016-01-25 19:22:28 -05:00
Eddie Hebert 930aa1b29b MAINT: Use metadata method for reader init.
Use the preexisting metadata method when instantiating the minute bar
reader.

An internal sublcass uses the `_get_metadata` method to setup data for
directories that have not used the new writer/reader interface.
(i.e. allows for reader creation when the metadata.json file does not
exist.)
2016-01-25 12:58:43 -05:00
Eddie Hebert 984e934e83 BUG: Fix OSError when creating sids that share dir
Fix a bug where creating a sid bcolz file when the containing directory
was already occupied by a sid caused an OSError on attempt of creating
the directory because it already existed.

e.g. if there were two sids, `1` and `2`. The paths would be
`00/00/000001.bcolz` and `00/00/000002.bcolz` which share the same
directory `00/00`.

Fixed by checking for directory existence before calling `makedirs`.

Add test coverage which exercises writing of sids that are siblings in
the sid directory structure.
2016-01-25 10:37:50 -05:00
Eddie Hebert 603a345e2d BUG: Allow writing on first day. 2016-01-21 11:10:57 -05:00
Eddie Hebert 3a8be8c624 BUG: Need to be able to append to minute ctable. 2016-01-21 11:10:07 -05:00
Eddie Hebert d5c3b5a15c ENH: Add writer for minute bcolz format.
Implement a writer for minute data into a format comprised of multiple
ctables, one for each individual asset, with a common 'index' shared by
all ctables where a given a dt maps to the same array index for all
equities and fields.

This format is pulled from the lazy-mainline/Q2.0 branch, with some
changes to the interface.

Add basic retrieval of values at a given dt to reader. Not yet used by
Zipline simulations, but added to support unit tests.

Also, rename stubbed out us_equity_minutes to minute_bars, since the
writer can be agnostic to asset type.
2016-01-21 10:54:27 -05:00
Scott Sanderson ec0abf1822 MAINT: Use coerce_string in BcolzDailyBarReader. 2016-01-12 17:39:44 -05:00
Scott Sanderson c8b80dddb0 BUG: Handle unicode adjustments path in py2.
In Python 2, passing unicode to SQLiteAdjustmentReader would fail to
coerce.
2016-01-12 17:39:36 -05:00
dmichalowicz 4f24a32c45 BUG: Benchmark and treasury curves data missing on first download 2015-12-21 13:38:24 -05:00
Eddie Hebert 8c1e52385f MAINT: Raise NotImplementedError in data_portal
The patch that added data_portal intended for NotImplementedError to be
raised if one of the functions was invoked, but the raise was omitted.
2015-12-15 17:08:19 -05:00
Eddie Hebert 6106cb98a5 REF: Remove unused parameter. 2015-12-14 14:26:06 -05:00
Eddie Hebert e5b5023d42 ENH: Add initial commit for DataPortal and readers
Moved from the `lazy-mainline` branch,
https://github.com/quantopian/zipline/pull/858

The intent of this patch to provide the basic class and readers
interfaces, developed on that branch, so that the use of creating the
object and opening paths etc. can be tested internally.

Additional changes beyond the lazy-mainline branch, addition of future
minute reader, and daily bar reader.

Also allow an argument of the future_daily_reader, though no such reader
yet exists.

It may be that future and equity readers share an interface, and a
further improvement would be providing an abstract base class.

co-author: @jbredeche <jean@quantopian.com>
2015-12-14 14:23:20 -05:00
Eddie Hebert 5f81acea05 ENH: Return -1 for missing spot prices.
Return -1 when there is a zero value for a spot price.
Intended for use by the incoming data portal changes. When the data
portal will see a -1 value, the portal will seek back a trading day
until a non-negative value is returned.
2015-11-25 11:32:36 -05:00
Eddie Hebert 53dae6320c BUG: Fix volume value returned by daily spot price
Volumes were incorrectly having the thousands factor applied, however
the volume is written as is (without the factor, since it volume is an
int, not float value.)

Fix by adding a special case for volume which returns the price as is.
2015-11-25 10:19:52 -05:00
Scott Sanderson 43ac9eab5c ENH: Check getmtime on download locations.
Rather than repeatedly try and fail to download data that's not yet
available, only try to download again if we haven't successfully
downloaded in the last hour.
2015-11-13 18:06:04 -05:00
Scott Sanderson 1b7d0c9477 MAINT: Add __future__ print function import.
We do print(stock) in this file, which happens to work in py2, but is
confusing.
2015-11-13 18:06:04 -05:00
Scott Sanderson 01888918dd MAINT: Use itemgetter instead of homegrown func. 2015-10-25 16:37:59 -04:00
Scott Sanderson 75f7c44223 BUG: Better check for last date.
Use get_loc to find the trading day that ended 2 days before now.
2015-10-25 16:37:59 -04:00
Scott Sanderson 8fd18e5aa6 DOC: Comment on treasury division by 100. 2015-10-25 16:37:59 -04:00