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.
Add a test case in test_algorithms to verify that appropriate exceptions are
thrown if an algorithm makes a call to the order api with a stop/limit price
and a style.
Add `style` parameter to order_value, order_percent, order_target,
order_target_percent, and order_target_value methods. The style parameter is
forwarded to the underlying call to `order`.
existing `limit_price` and `stop_price` parameters. The goal of this change is
to refactor the existing ordering API to provide a cleaner interface for
defining more complex order types.
Adds a new module, zipline.finance.execution, which defines the ExecutionStyle
abstract base class, along with concrete MarketOrder, LimitOrder, StopOrder,
and StopLimitOrder subclasses.
Adds a new `style` keyword argument to the function signature of the `order`
API method, which accepts an instance of ExecutionStyle.
The existing limit_price and stop_price parameters are still supported at this
time, but are converted into the new ExecutionStyle objects before being passed
to Blotter.order.
Fixes an issue where very low limit prices were being rounded to 0.0 and
effectively resulting in market orders. Adds an explicit check to test for
this behavior.
Adds a test algorithm that tries to buy with very high limit prices/very low
stop prices and tries to sell with very low limit prices/very high stop prices.
TradingAlgorithm always uses set_algo_instance in pairs of
set_algo_instance(self) and set_algo_instance(None). Refactoring this to use a
context manager.
The check of existence of the null return key, and the drop of said
return on every single bar was adding unneeded CPU time when an
algorithm was run with minute emissions.
Instead, add the 0.0 return with an index of the trading day before
the start date.
The removal of the `null return` was mainly in place so that the
period calculation was not crashing on a non-date index value;
with the index as a date, the period return can also approximate
volatility (even though the that volatility has high noise-to-signal
strength because it uses only two values as an input.)
The factoring out of the Sharpe calculation changed behavior
so that both period and cumulative return nans when there is
no volatility; however before that change period returned 0.0.
This breaks existing consumers which expected a non-nan value
for period results.
Smooth out that change by checking the value after the sharpe
has been calculated and reset nan's to 0.0
The calculations that are expected to change are:
- cumulative.beta
- cumulative.alpha
- cumulative.information
- cumulative.sharpe
- period.sortino
* Explanation of how risk calculations are changing
** Risk Fixes for Both Period and Cumulative
*** Downside Risk
Use sample instead of population for standard deviation.
Add a rounding factor, so that if the two values are close for a given
dt, that they do not count as a downside value, which would throw off
the denominator of the standard deviation of the downside diffs.
*** Standard Deviation Type
Across the board the standard deviation has been standardized to using
a 'sample' calculation, whereas before cumulative risk was monstly using
'population'. Using `ddof=1` with `np.std` calculates as if the values
are a sample.
** Cumulative Risk Fixes
*** Beta
Use the daily algorithm returns and benchmarks instead of annualized
mean returns.
*** Volatility
Use sample instead of population with standard deviation.
The volatility is an input to other calculations so this change affects
Sharpe and Information ratio calculations.
*** Information Ratio
The benchmark returns input is changed from annualized benchmark returns
to the annualized mean returns.
*** Alpha
The benchmark returns input is changed from annualized benchmark returns
to the annualized mean returns.
** Period Risk Fixes
*** Sortino
Use the downside risk of the daily return vs. the mean algorithm returns
for the minimum acceptable return instead of the treasury return.
The above required adding the calculation of the mean algorithm returns
for period risk.
Also, use algorithm_period_returns and tresaury_period_return as the
cumulative Sortino does, instead of using algorithm returns for both
inputs into the Sortino calculation.
* Other Supporting Changes
** answer_key
Add new mappings for downside risk and Sortino as well as
re-address the index mappings because of changes to the answer key
spread sheet.
** test_risk_cumulative
Change the decimal precision to expect higher precision.
The calculations are now more aligned with the answer key, so we can
expect higher precision. In particular now that the standard deviation
type matches everywhere in both the Python implementation and the answer
sheet, the precision of the first value no longer has to be glossed over.
** test_events_through_risk
Change the results which are used as a canary for risk changes,
since we do expect Sharpe to change with this change..
Change the algorithm volatility test to use the same iterkv style
as the rest of the suite, as it was useful to be able to zero in
on the offending date when debugging changes to the risk module.
Match the revisions found in the dev requirements file, so that the
versions used during development and continuous integration.
Pegging the versions in two separate places may end being brittle,
but suppress the build failure because the unpegged installation
of flake8 pulled in newer versions of pyflakes and pep8.
The risk unit tests were using the public Yahoo! data instead
of the returns from the answer key spreadsheet, change the RiskPeriod's
created in tests to use the values in the benchmark returns
column of the answer key.
Also, change the spreadsheet's benchmark volatility calculation
to use sample.
The use of population was exposed when the input values were
corrected.
Instead of the benchmarks' index, use the trading calendar to
populate the environment's trading days.
Remove `extra_date` field, since unlike the benchmarks list,
the trading calendar can generate future dates, so dates for
current day trading do not need to be appended.
Motivations:
- The source for the open and close/early close calendar and the
trading day calendar is now the same, which should help prevent
potential issues due to misalignment.
- Allows configurations where the benchmark is provided as a
generator based data source to need to supply a second benchmark
list just to populate dates.
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.
An oddity that was exposed while working on making the return series
passed to the risk module more exact, the series comparison between
the returns and mean returns was unbalanced, because the mean returns
were not masked down to the downside data points; however, in most,
if not all cases this was papered over by the call to `.valid()`
It seems more clear to get price values from
`self.trading_client.current_data[sid].price` than
from `self.portfolio.positions[sid].last_sale_price`.
The two values are the same, so this is just a readability change,
but it is also the same behavior as in `self.order_value()` and it's
good to have them all be the same.
The data zipline_transform.window is always evaluating to empty,
thus the actual checks are not being used because of the
`if not data` done before running the `asserts`.
This behavior should be fixed, and we should either remove the
`not data` check, or bubble up that the check is being hit too
many times; but in the meantime, disabling this test which takes
a non-trivial amount of time to run.
When run as an algorithm, outside of unit tests the talib wrapper
does work, so the cause of the window always being empty may be to
due to the machinery of the unit test.
Move the downside risk calculation into the main risk module;
so that the same calculation can eventually be used by both
the period and cumulative calculations, to prevent implementation
drift.