The "use_environment" decorator is too side-effectful (e.g.,
connecting to Yahoo! Finance or another data source) to be used as a
decorator to a function that gets evaluated during module load. This
causes problems, e.g., if Zipline is being used in a gevent
environment, when the trading environment created by the decorator
argument tries to use greenlets when gevent hasn't been fully
initialized.
Since the decorator is nothing more than a context-manager wrapper,
this commit removes the decorator and replaces its use with contexts,
i.e., "with" statements.
Raise exceptions when the slippage model returns transactions
that are non-sensical, i.e. those with zero volume, buy transactions
when the order is a sell (and vice-versa), and transactions that are
for a larger amount than the corresponding order.
TODO: After adding a unit test suite that covers just the blotter,
add tests that exercise this logic to that suite.
Instead of searching through the open orders to find the ones
that match the current transactions, now that simulate returns
the pair of transaction and order for which that transaction
was created for, that order can be used where we previously
searched for a modified order.
This should be a runtime improvement since, but not yet verified
via thorough profiling.
The TALib related tests randomly fail, skip for now, as it causes
noise when developing against the latest versions of the codebase.
Should remove skips when TALib is closer to being fully supported.
So that blotter.process_trade doesn't need to reindex the dictionary of
open orders, yield a tuple of (order, transaction) from simulate.
Also, update corresponding unit tests now that the method returns
a generator instead of a list.
Instead of using copysign with a param of 1, use `abs` to make the
code more clear between when slippage is using the absolute value,
and when it is creating an amount that uses the order direction.
To make implementing a custom slippage model more straightforward,
provide a simulate method that will setup the calling of
`process_order`, which individual slippage models override to
do the unique slippage handling, where the simulate method handles
the boilerplate of checking order triggers, etc.
In the volume share slippgae, the current amount had the direction,
i.e. buy/sell was baked into the value of `cur_amount` which then
needed to have the direction multiplied out when parts of the slippage
model needed to take in just the magnitude/amount into account.
So calculate the current volume, use that in calculations and then
apply at the order direction at order time.
Also, when applying the direction to the magnitude of the sell,
use copysign to make the code more explicit about taking the direction
of the order, instead of it possibly having some scalar impact.
As well as remove direction from volume_share calculation since that
calculation and subsequent calculations only care about the magnitude,
so make the disregard for direction more explicit by removing it.
Since `cur_amount` before it's changed by the direction, is always
a positive value, multiplying it back by the direction should also
always be positive.
Found that when implementing different slippage model, needed the
open amount in several places/functions, having the open amount
as a property of an order should help reduce the need for passing that
around and maintaining the value separately.
instead of just limiting it with max_date. This allows for an
additional "live" day appended to the end, fixing various uses
of the trading_day_map, and replacing the isolated check in
get_next_close.
- Change the expected type for order information from the string
of the order id to an `Order` object, so that it matches the same
abstraction level as passing in an event.
- Change the order (not to be confused with the parameter named `order`)
of the parameters so that they go from left to right in order of
static -> dynamic, i.e. the parameters most likely to change within
each invoration are the amount and price, with amount more likely
to change than price.
create_transaction accepted both sid and order, which in all cases
was derived from the current event, so remove `sid` and `order`,
replacing them with event
If there is a scenario where sid and order need to be set independently
of each other, then the underlying Transaction object can be called
directly.
Looking towards making writing custom slippage models slightly easier
by removing the redundancy.
Work towards a set_slippage method accepts a function that takes
event and orders as the argument, instead of being tightly bound
to using classes like FixedSlippage etc., in that scenario the
instances of SlippageModel will be used via `__call__`, so that
backwards compatiblity is maintained.
Now that the tradesimulation transform calls the blotter/slippage
within, instead of being wrapped in a slippage generator, the logging
for slippage can rely on the processor set within the tradesimulation
loop, instead of maintaining its own.
Now that the tradesimulation loop has changed to use benchmarks
as a 'clock', the logic for setting the current time can be grouped
together at the beginning of each iteration instead of the date
and snapshot grouping.
Also, can remove the snapshot_dt and use simulation_dt instead
of having two variables that were keeping track of the same value.
Also, it is no longer needed to peek into the data to get the first
simulation_dt now that simulation_dt is set at the beginning of each
loop iteration.
The check to filter out orders for zero shares wasn't truncated the
number of shares to an integer before checking, so if a fractional
amount less than 1 was being passed in, it wasn't being filtered out
even though it should have been. This is now fixed.