Previously the last sale price was not correctly being set on
positions when the transaction arrived before the trade event.
The last sale price was defaulted to zero and never updated. This resulted
in one holding stocks that were bough >>0 and now had value 0 from
the perspective of returns. The returns would display correctly again
when the next trade of that security happened. For most securities trading is
frequent enough that there's no issue, but for some illiquid ones it took
hours to fix itself.
Updated test_perf_tracking:TestPerformanceTracker.test_minute_tracker
This test was based on assuming that last_sale_price was zero,
allowing the sharpe ratio to be calculated. The sharpe ratio can no longer
be calculated for this specific tested scenario and the test has been changed
accordingly.
Removes support for handling dividends as part of the algorithm
simulation stream, replacing it with an API in `TradingAlgorithm` for
supplying dividends as a DataFrame.
The function that handles a market close for daily frequency changed from
`handle_market_close` to `handle_market_close_daily`.
The function that is called at on the closing minute each day when running
minutely changed from `handle_intraday_close` to
`handle_intraday_market_close`.
Make the portfolio property on TradingAlgorithm call `updated_portfolio`
internally. This prevents needless recomputation of the portfolio between
calls to `handle_data`, and also prevents issues where the portfolio object
could be unexpectedly modified in place in the body of a `handle_data` call.
Noteworthy finding in the course of investigating this bug:
If you modify a Python dictionary while iterating over it, the language will
only throw an exception if the size of the dictionary changes between loop
iterations; this means that you can do:
```
x = {1:1, 2:2, 3:3}
for k in x:
old_val = x[k]
del x[k]
x[f(k)] = old_val
print k
```
and you'll only get an error if f(k) is already a key in the dictionary.
This can lead to bizarre/nondeterministic behavior in the key iterator.
recent 2 for 1 stock split, where 1 class C share was distributed
for each share of class A held.
Now a dividend can specify a sid and ratio of stock that will be paid
to owners of the original security. If the ratio is 2.0, then for every
existing share, two shares will be paid.
In situations where the performance tracker has been reset or patched
to handle state juggling with warming up live data, the `market_close`
member of the performance tracker could end up out of sync with the
current algo time as determined by the
The symptom was dividends never triggering, because the end of day
checks would not match the current time.
Fix by having the tradesimulation loop be responsible, in minute/minute
mode, for advancing the market close and passing that value to the
performance tracker, instead of having the market close advanced by
the performance tracker as well.
Removed unnecessary parens
Keeping NameError reserved for when locals or globals are not found.
Exception is what we use for the other sid checks, so now they are consistent.
To help prevent algorithms from operating on positions that are
not in the existing universe of stocks.
Formerly, iterating over positions would return positions for stocks
which had zero shares held. (Where an explicit check in algorithm
code for `pos.amount != 0` could prevent from using a non-existent
position.)
Use the six module to import functions and types that are
consistent between Python 2 and 3, so that one code base can
support both versions.
- Use integer types instead of int and long.
- Use string_types instead of basestring.
- Account for iteritems, itervalues, iterkeys.
- Use six.moves for filter and zip, reduce
- Use compatible bytes for md5 hasher.
- xrange and range
In the performance period the max_leverage, max_capital_used,
cumulative_capital_used were calculated but not used.
At least one of those calculations, max_leverage, was causing a
divide by zero error.
Instead of papering over that error, the entire calculation was
a bit suspect so removing, with possibility of adding it back in
later with handling the case (or raising appropriate errors) when
the algorithm has little cash on hand.
Remove the lists of DailyReturn objects in favor of using pd.Series
to store the return values.
Should make it easier to inspect the values when stepping through,
make the windowing of data to a certain range more facile by using,
and have some performance increases due to removing object creation
and member access.
So that with minute data, 2.5 orders of magnitude of data can
be cut, allowing for longer window_lenghts, when the daily
values are what are desired for a signal.
Instead of using a raw np.array and keeping track of an index into
that array, use a pd.Series to track the last_sale_price and amounts
in a vector format.