TST: Reconciles tests with asset management system

This commit is contained in:
jfkirk
2015-06-08 16:30:16 -04:00
parent b84ac01cbf
commit a5d1f79a37
11 changed files with 608 additions and 391 deletions
+1 -2
View File
@@ -44,11 +44,10 @@
> running with minute data, then this will calculate the number of minutes in
> those days, accounting for early closes and the current time and apply the
> transform over the set of minutes. `returns` takes no parameters and will
> return the daily returns of the given security.
> return the daily returns of the given asset.
> Example:
```python
# The standard deviation of the price in the last 3 days.
data[security].stddev(3)
```
+147 -42
View File
@@ -36,6 +36,7 @@ from zipline.errors import (
RegisterTradingControlPostInit,
TradingControlViolation,
AccountControlViolation,
SymbolNotFound,
)
from zipline.test_algorithms import (
access_account_in_init,
@@ -55,6 +56,7 @@ from zipline.test_algorithms import (
TestTargetPercentAlgorithm,
TestTargetValueAlgorithm,
SetLongOnlyAlgorithm,
SetAssetDateBoundsAlgorithm,
SetMaxPositionSizeAlgorithm,
SetMaxOrderCountAlgorithm,
SetMaxOrderSizeAlgorithm,
@@ -85,6 +87,9 @@ from zipline.sources import (SpecificEquityTrades,
DataFrameSource,
DataPanelSource,
RandomWalkSource)
from zipline.assets import (
Equity, Future
)
from zipline.finance.execution import LimitOrder
from zipline.finance.trading import SimulationParameters
@@ -178,12 +183,12 @@ class TestMiscellaneousAPI(TestCase):
if algo.minute == 0:
# Should be filled by the next minute
algo.order(1, 1)
algo.order(algo.sid(1), 1)
# Won't be filled because the price is too low.
algo.order(2, 1, style=LimitOrder(0.01))
algo.order(2, 1, style=LimitOrder(0.01))
algo.order(2, 1, style=LimitOrder(0.01))
algo.order(algo.sid(2), 1, style=LimitOrder(0.01))
algo.order(algo.sid(2), 1, style=LimitOrder(0.01))
algo.order(algo.sid(2), 1, style=LimitOrder(0.01))
all_orders = algo.get_open_orders()
self.assertEqual(list(all_orders.keys()), [1, 2])
@@ -293,6 +298,58 @@ class TestMiscellaneousAPI(TestCase):
self.assertIs(composer, zipline.utils.events.ComposedRule.lazy_and)
def test_asset_lookup(self):
metadata = {0: {'symbol': 'PLAY',
'asset_type': 'equity',
'start_date': '2002-01-01',
'end_date': '2004-01-01'},
1: {'symbol': 'PLAY',
'asset_type': 'equity',
'start_date': '2005-01-01',
'end_date': '2006-01-01'},
2: {'symbol': 'OMG15',
'asset_type': 'future'}}
algo = TradingAlgorithm(asset_metadata=metadata)
# Test before either PLAY existed
algo.datetime = pd.Timestamp('2001-12-01', tz='UTC')
self.assertEqual(2, algo.symbol('OMG15'))
with self.assertRaises(SymbolNotFound):
algo.symbol('PLAY')
with self.assertRaises(SymbolNotFound):
algo.symbols('PLAY', 'OMG15')
# Test when first PLAY exists
algo.datetime = pd.Timestamp('2002-12-01', tz='UTC')
self.assertEqual(2, algo.symbol('OMG15'))
self.assertEqual(0, algo.symbol('PLAY'))
list_result = algo.symbols('PLAY', 'OMG15')
self.assertEqual(0, list_result[0])
self.assertEqual(2, list_result[1])
# Test after first PLAY ends
algo.datetime = pd.Timestamp('2004-12-01', tz='UTC')
self.assertEqual(2, algo.symbol('OMG15'))
self.assertEqual(0, algo.symbol('PLAY'))
# Test after second PLAY begins
algo.datetime = pd.Timestamp('2005-12-01', tz='UTC')
self.assertEqual(2, algo.symbol('OMG15'))
self.assertEqual(1, algo.symbol('PLAY'))
# Test after second PLAY ends
algo.datetime = pd.Timestamp('2006-12-01', tz='UTC')
self.assertEqual(2, algo.symbol('OMG15'))
self.assertEqual(1, algo.symbol('PLAY'))
list_result = algo.symbols('PLAY', 'OMG15')
self.assertEqual(1, list_result[0])
self.assertEqual(2, list_result[1])
# Test lookup SID
self.assertIsInstance(algo.sid(0), Equity)
self.assertIsInstance(algo.sid(1), Equity)
self.assertIsInstance(algo.sid(2), Future)
class TestTransformAlgorithm(TestCase):
def setUp(self):
@@ -384,19 +441,36 @@ class TestTransformAlgorithm(TestCase):
)
self.assertEqual(algo.sim_params.data_frequency, 'minute')
def test_order_methods(self):
AlgoClasses = [TestOrderAlgorithm,
TestOrderValueAlgorithm,
TestTargetAlgorithm,
TestOrderPercentAlgorithm,
TestTargetPercentAlgorithm,
TestTargetValueAlgorithm]
@parameterized.expand([
(TestOrderAlgorithm,),
(TestOrderValueAlgorithm,),
(TestTargetAlgorithm,),
(TestOrderPercentAlgorithm,),
(TestTargetPercentAlgorithm,),
(TestTargetValueAlgorithm,),
])
def test_order_methods(self, algo_class):
algo = algo_class(
sim_params=self.sim_params,
)
algo.run(self.df)
for AlgoClass in AlgoClasses:
algo = AlgoClass(
sim_params=self.sim_params,
)
algo.run(self.df)
@parameterized.expand([
(TestOrderAlgorithm,),
(TestOrderValueAlgorithm,),
(TestTargetAlgorithm,),
(TestOrderPercentAlgorithm,),
(TestTargetValueAlgorithm,),
])
def test_order_methods_for_future(self, algo_class):
metadata = {0: {'asset_type': 'future',
'contract_multiplier': 10}}
algo = algo_class(
sim_params=self.sim_params,
asset_metadata=metadata
)
algo.run(self.df)
def test_order_method_style_forwarding(self):
@@ -493,7 +567,8 @@ class TestAlgoScript(TestCase):
self.sim_params
)
self.source = SpecificEquityTrades(event_list=trade_history)
self.source = SpecificEquityTrades(sids=[133],
event_list=trade_history)
self.df_source, self.df = \
factory.create_test_df_source(self.sim_params)
@@ -543,7 +618,8 @@ from zipline.api import (slippage,
set_slippage,
set_commission,
order,
record)
record,
sid)
def initialize(context):
model = slippage.FixedSlippage(spread=0.10)
@@ -554,7 +630,7 @@ def initialize(context):
def handle_data(context, data):
if context.incr < context.count:
order(0, -1000)
order(sid(0), -1000)
record(price=data[0].price)
context.incr += 1""",
@@ -607,7 +683,7 @@ def handle_data(context, data):
if context.incr < context.count:
# order small lots to be sure the
# order will fill in a single transaction
order(0, 5000)
order(sid(0), 5000)
record(price=data[0].price)
record(volume=data[0].volume)
record(incr=context.incr)
@@ -877,6 +953,7 @@ class TestGetDatetime(TestCase):
algo = TradingAlgorithm(
script=algo,
sim_params=sim_params,
identifiers=[1]
)
algo.run(source)
self.assertFalse(algo.first_bar)
@@ -923,7 +1000,7 @@ class TestTradingControls(TestCase):
# Buy one share four times. Should be fine.
def handle_data(algo, data):
algo.order(self.sid, 1)
algo.order(algo.sid(self.sid), 1)
algo.order_count += 1
algo = SetMaxPositionSizeAlgorithm(sid=self.sid,
max_shares=10,
@@ -933,7 +1010,7 @@ class TestTradingControls(TestCase):
# Buy three shares four times. Should bail on the fourth before it's
# placed.
def handle_data(algo, data):
algo.order(self.sid, 3)
algo.order(algo.sid(self.sid), 3)
algo.order_count += 1
algo = SetMaxPositionSizeAlgorithm(sid=self.sid,
@@ -944,7 +1021,7 @@ class TestTradingControls(TestCase):
# Buy two shares four times. Should bail due to max_notional on the
# third attempt.
def handle_data(algo, data):
algo.order(self.sid, 3)
algo.order(algo.sid(self.sid), 3)
algo.order_count += 1
algo = SetMaxPositionSizeAlgorithm(sid=self.sid,
@@ -955,7 +1032,7 @@ class TestTradingControls(TestCase):
# Set the trading control to a different sid, then BUY ALL THE THINGS!.
# Should continue normally.
def handle_data(algo, data):
algo.order(self.sid, 10000)
algo.order(algo.sid(self.sid), 10000)
algo.order_count += 1
algo = SetMaxPositionSizeAlgorithm(sid=self.sid + 1,
max_shares=10,
@@ -965,7 +1042,7 @@ class TestTradingControls(TestCase):
# Set the trading control sid to None, then BUY ALL THE THINGS!. Should
# fail because setting sid to None makes the control apply to all sids.
def handle_data(algo, data):
algo.order(self.sid, 10000)
algo.order(algo.sid(self.sid), 10000)
algo.order_count += 1
algo = SetMaxPositionSizeAlgorithm(max_shares=10, max_notional=61.0)
self.check_algo_fails(algo, handle_data, 0)
@@ -977,7 +1054,7 @@ class TestTradingControls(TestCase):
restricted_list=[self.sid])
def handle_data(algo, data):
algo.order(self.sid, 100)
algo.order(algo.sid(self.sid), 100)
algo.order_count += 1
self.check_algo_fails(algo, handle_data, 0)
@@ -988,7 +1065,7 @@ class TestTradingControls(TestCase):
restricted_list=[134, 135, 136])
def handle_data(algo, data):
algo.order(self.sid, 100)
algo.order(algo.sid(self.sid), 100)
algo.order_count += 1
self.check_algo_succeeds(algo, handle_data)
@@ -997,7 +1074,7 @@ class TestTradingControls(TestCase):
# Buy one share.
def handle_data(algo, data):
algo.order(self.sid, 1)
algo.order(algo.sid(self.sid), 1)
algo.order_count += 1
algo = SetMaxOrderSizeAlgorithm(sid=self.sid,
max_shares=10,
@@ -1007,7 +1084,7 @@ class TestTradingControls(TestCase):
# Buy 1, then 2, then 3, then 4 shares. Bail on the last attempt
# because we exceed shares.
def handle_data(algo, data):
algo.order(self.sid, algo.order_count + 1)
algo.order(algo.sid(self.sid), algo.order_count + 1)
algo.order_count += 1
algo = SetMaxOrderSizeAlgorithm(sid=self.sid,
@@ -1018,7 +1095,7 @@ class TestTradingControls(TestCase):
# Buy 1, then 2, then 3, then 4 shares. Bail on the last attempt
# because we exceed notional.
def handle_data(algo, data):
algo.order(self.sid, algo.order_count + 1)
algo.order(algo.sid(self.sid), algo.order_count + 1)
algo.order_count += 1
algo = SetMaxOrderSizeAlgorithm(sid=self.sid,
@@ -1029,7 +1106,7 @@ class TestTradingControls(TestCase):
# Set the trading control to a different sid, then BUY ALL THE THINGS!.
# Should continue normally.
def handle_data(algo, data):
algo.order(self.sid, 10000)
algo.order(algo.sid(self.sid), 10000)
algo.order_count += 1
algo = SetMaxOrderSizeAlgorithm(sid=self.sid + 1,
max_shares=1,
@@ -1040,7 +1117,7 @@ class TestTradingControls(TestCase):
# Should fail because not specifying a sid makes the trading control
# apply to all sids.
def handle_data(algo, data):
algo.order(self.sid, 10000)
algo.order(algo.sid(self.sid), 10000)
algo.order_count += 1
algo = SetMaxOrderSizeAlgorithm(max_shares=1,
max_notional=1.0)
@@ -1061,7 +1138,7 @@ class TestTradingControls(TestCase):
def handle_data(algo, data):
for i in range(5):
algo.order(self.sid, 1)
algo.order(algo.sid(self.sid), 1)
algo.order_count += 1
algo = SetMaxOrderCountAlgorithm(3)
@@ -1080,7 +1157,7 @@ class TestTradingControls(TestCase):
def test_long_only(self):
# Sell immediately -> fail immediately.
def handle_data(algo, data):
algo.order(self.sid, -1)
algo.order(algo.sid(self.sid), -1)
algo.order_count += 1
algo = SetLongOnlyAlgorithm()
self.check_algo_fails(algo, handle_data, 0)
@@ -1089,9 +1166,9 @@ class TestTradingControls(TestCase):
# should succeed.
def handle_data(algo, data):
if (algo.order_count % 2) == 0:
algo.order(self.sid, 1)
algo.order(algo.sid(self.sid), 1)
else:
algo.order(self.sid, -1)
algo.order(algo.sid(self.sid), -1)
algo.order_count += 1
algo = SetLongOnlyAlgorithm()
self.check_algo_succeeds(algo, handle_data)
@@ -1099,7 +1176,7 @@ class TestTradingControls(TestCase):
# Buy on first three days, then sell off holdings. Should succeed.
def handle_data(algo, data):
amounts = [1, 1, 1, -3]
algo.order(self.sid, amounts[algo.order_count])
algo.order(algo.sid(self.sid), amounts[algo.order_count])
algo.order_count += 1
algo = SetLongOnlyAlgorithm()
self.check_algo_succeeds(algo, handle_data)
@@ -1108,7 +1185,7 @@ class TestTradingControls(TestCase):
# Should fail on the last sale.
def handle_data(algo, data):
amounts = [1, 1, 1, -4]
algo.order(self.sid, amounts[algo.order_count])
algo.order(algo.sid(self.sid), amounts[algo.order_count])
algo.order_count += 1
algo = SetLongOnlyAlgorithm()
self.check_algo_fails(algo, handle_data, 3)
@@ -1134,14 +1211,42 @@ class TestTradingControls(TestCase):
algo.run(self.source)
self.source.rewind()
def test_asset_date_bounds(self):
# Run the algorithm with a sid that ends far in the future
df_source, _ = factory.create_test_df_source(self.sim_params)
metadata = {0: {'start_date': '1990-01-01',
'end_date': '2020-01-01'}}
algo = SetAssetDateBoundsAlgorithm(asset_metadata=metadata,
sim_params=self.sim_params,)
algo.run(df_source)
# Run the algorithm with a sid that has already ended
df_source, _ = factory.create_test_df_source(self.sim_params)
metadata = {0: {'start_date': '1989-01-01',
'end_date': '1990-01-01'}}
algo = SetAssetDateBoundsAlgorithm(asset_metadata=metadata,
sim_params=self.sim_params,)
with self.assertRaises(TradingControlViolation):
algo.run(df_source)
# Run the algorithm with a sid that has not started
df_source, _ = factory.create_test_df_source(self.sim_params)
metadata = {0: {'start_date': '2020-01-01',
'end_date': '2021-01-01'}}
algo = SetAssetDateBoundsAlgorithm(asset_metadata=metadata,
sim_params=self.sim_params,)
with self.assertRaises(TradingControlViolation):
algo.run(df_source)
class TestAccountControls(TestCase):
def setUp(self):
self.sim_params = factory.create_simulation_parameters(num_days=4)
self.sid = 133
self.sidint = 133
self.trade_history = factory.create_trade_history(
self.sid,
self.sidint,
[10.0, 10.0, 11.0, 11.0],
[100, 100, 100, 300],
timedelta(days=1),
@@ -1173,14 +1278,14 @@ class TestAccountControls(TestCase):
# Set max leverage to 0 so buying one share fails.
def handle_data(algo, data):
algo.order(self.sid, 1)
algo.order(algo.sid(self.sidint), 1)
algo = SetMaxLeverageAlgorithm(0)
self.check_algo_fails(algo, handle_data)
# Set max leverage to 1 so buying one share passes
def handle_data(algo, data):
algo.order(self.sid, 1)
algo.order(algo.sid(self.sidint), 1)
algo = SetMaxLeverageAlgorithm(1)
self.check_algo_succeeds(algo, handle_data)
+5 -6
View File
@@ -62,7 +62,7 @@ class TestAlgo(TradingAlgorithm):
self.latest_date = None
self.set_slippage(RecordDateSlippage(spread=0.05))
self.stocks = [8229]
self.stocks = [self.sid(8229)]
self.ordered = False
self.num_bars = 0
@@ -105,7 +105,7 @@ class AlgorithmGeneratorTestCase(TestCase):
start=datetime(2012, 5, 1, tzinfo=pytz.utc),
end=datetime(2012, 6, 30, tzinfo=pytz.utc)
)
algo = TestAlgo(self, sim_params=sim_params)
algo = TestAlgo(self, identifiers=[8229], sim_params=sim_params)
trade_source = factory.create_daily_trade_source(
[8229],
200,
@@ -131,7 +131,7 @@ class AlgorithmGeneratorTestCase(TestCase):
start=datetime(2011, 7, 30, tzinfo=pytz.utc),
end=datetime(2012, 7, 30, tzinfo=pytz.utc)
)
algo = TestAlgo(self, sim_params=sim_params)
algo = TestAlgo(self, identifiers=[8229], sim_params=sim_params)
trade_source = factory.create_daily_trade_source(
[8229],
sim_params
@@ -158,8 +158,7 @@ class AlgorithmGeneratorTestCase(TestCase):
period_end=datetime(2012, 7, 30, tzinfo=pytz.utc),
data_frequency='minute'
)
algo = TestAlgo(self,
sim_params=sim_params)
algo = TestAlgo(self, identifiers=[8229], sim_params=sim_params)
midnight_custom_source = [Event({
'custom_field': 42.0,
@@ -223,6 +222,6 @@ class AlgorithmGeneratorTestCase(TestCase):
"""
sim_params = create_simulation_parameters(num_days=1,
data_frequency='minute')
algo = TestAlgo(self, sim_params=sim_params)
algo = TestAlgo(self, sim_params=sim_params, identifiers=[8229])
algo.run(source=[], overwrite_sim_params=False)
self.assertEqual(algo.datetime, sim_params.last_close)
+4 -1
View File
@@ -112,7 +112,10 @@ class TestChangeOfSids(TestCase):
)
def test_all_sids_passed(self):
algo = BatchTransformAlgorithmSetSid(sim_params=self.sim_params)
algo = BatchTransformAlgorithmSetSid(
sim_params=self.sim_params,
identifiers=[i for i in range(0, 90)]
)
source = DifferentSidSource()
algo.run(source)
for i, (df, date) in enumerate(zip(algo.history, source.trading_days)):
+4 -1
View File
@@ -18,6 +18,7 @@ from nose_parameterized import parameterized
from unittest import TestCase
from zipline.finance.blotter import Blotter, ORDER_STATUS
from zipline.finance.trading import with_environment
from zipline.finance.execution import (
LimitOrder,
MarketOrder,
@@ -34,8 +35,10 @@ from zipline.utils.test_utils import(
class BlotterTestCase(TestCase):
def setUp(self):
@with_environment()
def setUp(self, env=None):
setup_logger(self)
env.update_asset_finder(identifiers=[24])
def tearDown(self):
teardown_logger(self)
+4 -2
View File
@@ -46,7 +46,8 @@ start=1990-1-1
self.assertEqual(args['algofile'], 'test.py')
self.assertEqual(args['symbols'], 'test_symbols')
self.assertEqual(args['start'], '1990-1-1')
self.assertEqual(args['end'], cli.DEFAULTS['end'])
self.assertEqual(args['data_frequency'],
cli.DEFAULTS['data_frequency'])
finally:
os.remove('test.conf')
@@ -63,6 +64,7 @@ start=1990-1-1
# Non-overwritten values
self.assertEqual(args['symbols'], 'test_symbols')
# Default values
self.assertEqual(args['end'], cli.DEFAULTS['end'])
self.assertEqual(args['data_frequency'],
cli.DEFAULTS['data_frequency'])
finally:
os.remove('test.conf')
+3 -1
View File
@@ -37,7 +37,7 @@ class BuyAndHoldAlgorithm(TradingAlgorithm):
def handle_data(self, data):
if not self.holding:
self.order(self.SID_TO_BUY_AND_HOLD, 100)
self.order(self.sid(self.SID_TO_BUY_AND_HOLD), 100)
self.holding = True
@@ -68,6 +68,7 @@ class TestEventsThroughRisk(unittest.TestCase):
)
algo = BuyAndHoldAlgorithm(
identifiers=[1],
sim_params=sim_params)
first_date = datetime.datetime(2006, 1, 3, tzinfo=pytz.utc)
@@ -188,6 +189,7 @@ class TestEventsThroughRisk(unittest.TestCase):
data_frequency='minute')
algo = BuyAndHoldAlgorithm(
identifiers=[1],
sim_params=sim_params)
first_date = datetime.datetime(2006, 1, 3, tzinfo=pytz.utc)
+2 -1
View File
@@ -509,7 +509,8 @@ def handle_data(context, data):
test_algo = TradingAlgorithm(
script=algo_text,
data_frequency='minute',
sim_params=sim_params
sim_params=sim_params,
identifiers=[0]
)
source = RandomWalkSource(start=start,
+350 -281
View File
@@ -43,7 +43,7 @@ from zipline.gens.composites import date_sorted_sources
from zipline.finance.trading import SimulationParameters
from zipline.finance.blotter import Order
from zipline.finance.commission import PerShare, PerTrade, PerDollar
from zipline.finance import trading
from zipline.finance.trading import with_environment
from zipline.utils.factory import create_random_simulation_parameters
import zipline.protocol as zp
from zipline.protocol import Event, DATASOURCE_TYPE
@@ -127,7 +127,8 @@ def create_txn(trade_event, price, amount):
return create_transaction(trade_event, mock_order, price, amount)
def benchmark_events_in_range(sim_params):
@with_environment()
def benchmark_events_in_range(sim_params, env=None):
return [
Event({'dt': dt,
'returns': ret,
@@ -135,7 +136,7 @@ def benchmark_events_in_range(sim_params):
# We explicitly rely on the behavior that benchmarks sort before
# any other events.
'source_id': '1Abenchmarks'})
for dt, ret in trading.environment.benchmark_returns.iteritems()
for dt, ret in env.benchmark_returns.iteritems()
if dt.date() >= sim_params.period_start.date() and
dt.date() <= sim_params.period_end.date()
]
@@ -368,79 +369,78 @@ class TestCommissionEvents(unittest.TestCase):
self.benchmark_events = benchmark_events_in_range(self.sim_params)
def test_commission_event(self):
with trading.TradingEnvironment():
events = factory.create_trade_history(
1,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params
)
events = factory.create_trade_history(
1,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params
)
# Test commission models and validate result
# Expected commission amounts:
# PerShare commission: 1.00, 1.00, 1.50 = $3.50
# PerTrade commission: 5.00, 5.00, 5.00 = $15.00
# PerDollar commission: 1.50, 3.00, 4.50 = $9.00
# Total commission = $3.50 + $15.00 + $9.00 = $27.50
# Test commission models and validate result
# Expected commission amounts:
# PerShare commission: 1.00, 1.00, 1.50 = $3.50
# PerTrade commission: 5.00, 5.00, 5.00 = $15.00
# PerDollar commission: 1.50, 3.00, 4.50 = $9.00
# Total commission = $3.50 + $15.00 + $9.00 = $27.50
# Create 3 transactions: 50, 100, 150 shares traded @ $20
transactions = [create_txn(events[0], 20, i)
for i in [50, 100, 150]]
# Create 3 transactions: 50, 100, 150 shares traded @ $20
transactions = [create_txn(events[0], 20, i)
for i in [50, 100, 150]]
# Create commission models and validate that produce expected
# commissions.
models = [PerShare(cost=0.01, min_trade_cost=1.00),
PerTrade(cost=5.00),
PerDollar(cost=0.0015)]
expected_results = [3.50, 15.0, 9.0]
# Create commission models and validate that produce expected
# commissions.
models = [PerShare(cost=0.01, min_trade_cost=1.00),
PerTrade(cost=5.00),
PerDollar(cost=0.0015)]
expected_results = [3.50, 15.0, 9.0]
for model, expected in zip(models, expected_results):
total_commission = 0
for trade in transactions:
total_commission += model.calculate(trade)[1]
self.assertEqual(total_commission, expected)
for model, expected in zip(models, expected_results):
total_commission = 0
for trade in transactions:
total_commission += model.calculate(trade)[1]
self.assertEqual(total_commission, expected)
# Verify that commission events are handled correctly by
# PerformanceTracker.
cash_adj_dt = events[0].dt
cash_adjustment = factory.create_commission(1, 300.0, cash_adj_dt)
events.append(cash_adjustment)
# Verify that commission events are handled correctly by
# PerformanceTracker.
cash_adj_dt = events[0].dt
cash_adjustment = factory.create_commission(1, 300.0, cash_adj_dt)
events.append(cash_adjustment)
# Insert a purchase order.
txns = [create_txn(events[0], 20, 1)]
results = calculate_results(self, events, txns=txns)
# Insert a purchase order.
txns = [create_txn(events[0], 20, 1)]
results = calculate_results(self, events, txns=txns)
# Validate that we lost 320 dollars from our cash pool.
self.assertEqual(results[-1]['cumulative_perf']['ending_cash'],
9680)
# Validate that the cost basis of our position changed.
self.assertEqual(results[-1]['daily_perf']['positions']
[0]['cost_basis'], 320.0)
# Validate that the account attributes were updated.
account = results[1]['account']
self.assertEqual(float('inf'), account['day_trades_remaining'])
np.testing.assert_allclose(0.001, account['leverage'], rtol=1e-3,
atol=1e-4)
np.testing.assert_allclose(9680, account['regt_equity'], rtol=1e-3)
self.assertEqual(float('inf'), account['regt_margin'])
np.testing.assert_allclose(9680, account['available_funds'],
rtol=1e-3)
self.assertEqual(0, account['maintenance_margin_requirement'])
np.testing.assert_allclose(9690,
account['equity_with_loan'], rtol=1e-3)
self.assertEqual(float('inf'), account['buying_power'])
self.assertEqual(0, account['initial_margin_requirement'])
np.testing.assert_allclose(9680, account['excess_liquidity'],
rtol=1e-3)
np.testing.assert_allclose(9680, account['settled_cash'],
rtol=1e-3)
np.testing.assert_allclose(9690, account['net_liquidation'],
rtol=1e-3)
np.testing.assert_allclose(0.999, account['cushion'], rtol=1e-3)
np.testing.assert_allclose(10, account['total_positions_value'],
rtol=1e-3)
self.assertEqual(0, account['accrued_interest'])
# Validate that we lost 320 dollars from our cash pool.
self.assertEqual(results[-1]['cumulative_perf']['ending_cash'],
9680)
# Validate that the cost basis of our position changed.
self.assertEqual(results[-1]['daily_perf']['positions']
[0]['cost_basis'], 320.0)
# Validate that the account attributes were updated.
account = results[1]['account']
self.assertEqual(float('inf'), account['day_trades_remaining'])
np.testing.assert_allclose(0.001, account['leverage'], rtol=1e-3,
atol=1e-4)
np.testing.assert_allclose(9680, account['regt_equity'], rtol=1e-3)
self.assertEqual(float('inf'), account['regt_margin'])
np.testing.assert_allclose(9680, account['available_funds'],
rtol=1e-3)
self.assertEqual(0, account['maintenance_margin_requirement'])
np.testing.assert_allclose(9690,
account['equity_with_loan'], rtol=1e-3)
self.assertEqual(float('inf'), account['buying_power'])
self.assertEqual(0, account['initial_margin_requirement'])
np.testing.assert_allclose(9680, account['excess_liquidity'],
rtol=1e-3)
np.testing.assert_allclose(9680, account['settled_cash'],
rtol=1e-3)
np.testing.assert_allclose(9690, account['net_liquidation'],
rtol=1e-3)
np.testing.assert_allclose(0.999, account['cushion'], rtol=1e-3)
np.testing.assert_allclose(10, account['total_positions_value'],
rtol=1e-3)
self.assertEqual(0, account['accrued_interest'])
def test_commission_zero_position(self):
"""
@@ -476,24 +476,23 @@ class TestCommissionEvents(unittest.TestCase):
"""
Ensure no position-not-found or sid-not-found errors.
"""
with trading.TradingEnvironment():
events = factory.create_trade_history(
1,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params
)
events = factory.create_trade_history(
1,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params
)
# Add a cash adjustment at the time of event[3].
cash_adj_dt = events[3].dt
cash_adjustment = factory.create_commission(1, 300.0, cash_adj_dt)
events.append(cash_adjustment)
# Add a cash adjustment at the time of event[3].
cash_adj_dt = events[3].dt
cash_adjustment = factory.create_commission(1, 300.0, cash_adj_dt)
events.append(cash_adjustment)
results = calculate_results(self, events)
# Validate that we lost 300 dollars from our cash pool.
self.assertEqual(results[-1]['cumulative_perf']['ending_cash'],
9700)
results = calculate_results(self, events)
# Validate that we lost 300 dollars from our cash pool.
self.assertEqual(results[-1]['cumulative_perf']['ending_cash'],
9700)
class TestDividendPerformance(unittest.TestCase):
@@ -508,117 +507,114 @@ class TestDividendPerformance(unittest.TestCase):
self.benchmark_events = benchmark_events_in_range(self.sim_params)
def test_market_hours_calculations(self):
with trading.TradingEnvironment():
# DST in US/Eastern began on Sunday March 14, 2010
before = datetime(2010, 3, 12, 14, 31, tzinfo=pytz.utc)
after = factory.get_next_trading_dt(
before,
timedelta(days=1)
)
self.assertEqual(after.hour, 13)
# DST in US/Eastern began on Sunday March 14, 2010
before = datetime(2010, 3, 12, 14, 31, tzinfo=pytz.utc)
after = factory.get_next_trading_dt(
before,
timedelta(days=1)
)
self.assertEqual(after.hour, 13)
def test_long_position_receives_dividend(self):
with trading.TradingEnvironment():
# post some trades in the market
events = factory.create_trade_history(
1,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params
)
dividend = factory.create_dividend(
1,
10.00,
# declared date, when the algorithm finds out about
# the dividend
events[0].dt,
# ex_date, the date before which the algorithm must hold stock
# to receive the dividend
events[1].dt,
# pay date, when the algorithm receives the dividend.
events[2].dt
)
# post some trades in the market
events = factory.create_trade_history(
1,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params
)
dividend = factory.create_dividend(
1,
10.00,
# declared date, when the algorithm finds out about
# the dividend
events[0].dt,
# ex_date, the date before which the algorithm must hold stock
# to receive the dividend
events[1].dt,
# pay date, when the algorithm receives the dividend.
events[2].dt
)
# Simulate a transaction being filled prior to the ex_date.
txns = [create_txn(events[0], 10.0, 100)]
results = calculate_results(
self,
events,
dividend_events=[dividend],
txns=txns,
)
# Simulate a transaction being filled prior to the ex_date.
txns = [create_txn(events[0], 10.0, 100)]
results = calculate_results(
self,
events,
dividend_events=[dividend],
txns=txns,
)
self.assertEqual(len(results), 5)
cumulative_returns = \
[event['cumulative_perf']['returns'] for event in results]
self.assertEqual(cumulative_returns, [0.0, 0.0, 0.1, 0.1, 0.1])
daily_returns = [event['daily_perf']['returns']
for event in results]
self.assertEqual(daily_returns, [0.0, 0.0, 0.10, 0.0, 0.0])
cash_flows = [event['daily_perf']['capital_used']
for event in results]
self.assertEqual(cash_flows, [-1000, 0, 1000, 0, 0])
cumulative_cash_flows = \
[event['cumulative_perf']['capital_used'] for event in results]
self.assertEqual(cumulative_cash_flows, [-1000, -1000, 0, 0, 0])
cash_pos = \
[event['cumulative_perf']['ending_cash'] for event in results]
self.assertEqual(cash_pos, [9000, 9000, 10000, 10000, 10000])
self.assertEqual(len(results), 5)
cumulative_returns = \
[event['cumulative_perf']['returns'] for event in results]
self.assertEqual(cumulative_returns, [0.0, 0.0, 0.1, 0.1, 0.1])
daily_returns = [event['daily_perf']['returns']
for event in results]
self.assertEqual(daily_returns, [0.0, 0.0, 0.10, 0.0, 0.0])
cash_flows = [event['daily_perf']['capital_used']
for event in results]
self.assertEqual(cash_flows, [-1000, 0, 1000, 0, 0])
cumulative_cash_flows = \
[event['cumulative_perf']['capital_used'] for event in results]
self.assertEqual(cumulative_cash_flows, [-1000, -1000, 0, 0, 0])
cash_pos = \
[event['cumulative_perf']['ending_cash'] for event in results]
self.assertEqual(cash_pos, [9000, 9000, 10000, 10000, 10000])
def test_long_position_receives_stock_dividend(self):
with trading.TradingEnvironment():
# post some trades in the market
events = []
for sid in (1, 2):
events.extend(
factory.create_trade_history(
sid,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params)
)
dividend = factory.create_stock_dividend(
1,
payment_sid=2,
ratio=2,
# declared date, when the algorithm finds out about
# the dividend
declared_date=events[0].dt,
# ex_date, the date before which the algorithm must hold stock
# to receive the dividend
ex_date=events[1].dt,
# pay date, when the algorithm receives the dividend.
pay_date=events[2].dt
# post some trades in the market
events = []
for sid in (1, 2):
events.extend(
factory.create_trade_history(
sid,
[10, 10, 10, 10, 10],
[100, 100, 100, 100, 100],
oneday,
self.sim_params)
)
txns = [create_txn(events[0], 10.0, 100)]
dividend = factory.create_stock_dividend(
1,
payment_sid=2,
ratio=2,
# declared date, when the algorithm finds out about
# the dividend
declared_date=events[0].dt,
# ex_date, the date before which the algorithm must hold stock
# to receive the dividend
ex_date=events[1].dt,
# pay date, when the algorithm receives the dividend.
pay_date=events[2].dt
)
results = calculate_results(
self,
events,
dividend_events=[dividend],
txns=txns,
)
txns = [create_txn(events[0], 10.0, 100)]
self.assertEqual(len(results), 5)
cumulative_returns = \
[event['cumulative_perf']['returns'] for event in results]
self.assertEqual(cumulative_returns, [0.0, 0.0, 0.2, 0.2, 0.2])
daily_returns = [event['daily_perf']['returns']
for event in results]
self.assertEqual(daily_returns, [0.0, 0.0, 0.2, 0.0, 0.0])
cash_flows = [event['daily_perf']['capital_used']
for event in results]
self.assertEqual(cash_flows, [-1000, 0, 0, 0, 0])
cumulative_cash_flows = \
[event['cumulative_perf']['capital_used'] for event in results]
self.assertEqual(cumulative_cash_flows, [-1000] * 5)
cash_pos = \
[event['cumulative_perf']['ending_cash'] for event in results]
self.assertEqual(cash_pos, [9000] * 5)
results = calculate_results(
self,
events,
dividend_events=[dividend],
txns=txns,
)
self.assertEqual(len(results), 5)
cumulative_returns = \
[event['cumulative_perf']['returns'] for event in results]
self.assertEqual(cumulative_returns, [0.0, 0.0, 0.2, 0.2, 0.2])
daily_returns = [event['daily_perf']['returns']
for event in results]
self.assertEqual(daily_returns, [0.0, 0.0, 0.2, 0.0, 0.0])
cash_flows = [event['daily_perf']['capital_used']
for event in results]
self.assertEqual(cash_flows, [-1000, 0, 0, 0, 0])
cumulative_cash_flows = \
[event['cumulative_perf']['capital_used'] for event in results]
self.assertEqual(cumulative_cash_flows, [-1000] * 5)
cash_pos = \
[event['cumulative_perf']['ending_cash'] for event in results]
self.assertEqual(cash_pos, [9000] * 5)
def test_long_position_purchased_on_ex_date_receives_no_dividend(self):
# post some trades in the market
@@ -1831,112 +1827,115 @@ class TestPerformanceTracker(unittest.TestCase):
else:
yield event
def test_minute_tracker(self):
@with_environment()
def test_minute_tracker(self, env=None):
""" Tests minute performance tracking."""
with trading.TradingEnvironment():
start_dt = trading.environment.exchange_dt_in_utc(
datetime(2013, 3, 1, 9, 31))
end_dt = trading.environment.exchange_dt_in_utc(
datetime(2013, 3, 1, 16, 0))
start_dt = env.exchange_dt_in_utc(datetime(2013, 3, 1, 9, 31))
end_dt = env.exchange_dt_in_utc(datetime(2013, 3, 1, 16, 0))
sim_params = SimulationParameters(
period_start=start_dt,
period_end=end_dt,
emission_rate='minute'
)
tracker = perf.PerformanceTracker(sim_params)
sim_params = SimulationParameters(
period_start=start_dt,
period_end=end_dt,
emission_rate='minute'
)
tracker = perf.PerformanceTracker(sim_params)
foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt)
order_event_1 = Order(sid=foo_event_1.sid,
foosid = 1
barsid = 2
env.update_asset_finder(identifiers=[foosid, barsid])
foo_event_1 = factory.create_trade(foosid, 10.0, 20, start_dt)
order_event_1 = Order(sid=foo_event_1.sid,
amount=-25,
dt=foo_event_1.dt)
bar_event_1 = factory.create_trade(barsid, 100.0, 200, start_dt)
txn_event_1 = Transaction(sid=foo_event_1.sid,
amount=-25,
dt=foo_event_1.dt)
bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt)
txn_event_1 = Transaction(sid=foo_event_1.sid,
amount=-25,
dt=foo_event_1.dt,
price=10.0,
commission=0.50,
order_id=order_event_1.id)
benchmark_event_1 = Event({
'dt': start_dt,
'returns': 0.01,
'type': zp.DATASOURCE_TYPE.BENCHMARK
})
dt=foo_event_1.dt,
price=10.0,
commission=0.50,
order_id=order_event_1.id)
benchmark_event_1 = Event({
'dt': start_dt,
'returns': 0.01,
'type': zp.DATASOURCE_TYPE.BENCHMARK
})
foo_event_2 = factory.create_trade(
'foo', 11.0, 20, start_dt + timedelta(minutes=1))
bar_event_2 = factory.create_trade(
'bar', 11.0, 20, start_dt + timedelta(minutes=1))
benchmark_event_2 = Event({
'dt': start_dt + timedelta(minutes=1),
'returns': 0.02,
'type': zp.DATASOURCE_TYPE.BENCHMARK
})
foo_event_2 = factory.create_trade(
foosid, 11.0, 20, start_dt + timedelta(minutes=1))
bar_event_2 = factory.create_trade(
barsid, 11.0, 20, start_dt + timedelta(minutes=1))
benchmark_event_2 = Event({
'dt': start_dt + timedelta(minutes=1),
'returns': 0.02,
'type': zp.DATASOURCE_TYPE.BENCHMARK
})
events = [
foo_event_1,
order_event_1,
benchmark_event_1,
txn_event_1,
bar_event_1,
foo_event_2,
benchmark_event_2,
bar_event_2,
]
events = [
foo_event_1,
order_event_1,
benchmark_event_1,
txn_event_1,
bar_event_1,
foo_event_2,
benchmark_event_2,
bar_event_2,
]
grouped_events = itertools.groupby(
events, operator.attrgetter('dt'))
grouped_events = itertools.groupby(
events, operator.attrgetter('dt'))
messages = {}
for date, group in grouped_events:
tracker.set_date(date)
for event in group:
if event.type == zp.DATASOURCE_TYPE.TRADE:
tracker.process_trade(event)
elif event.type == zp.DATASOURCE_TYPE.BENCHMARK:
tracker.process_benchmark(event)
elif event.type == zp.DATASOURCE_TYPE.ORDER:
tracker.process_order(event)
elif event.type == zp.DATASOURCE_TYPE.TRANSACTION:
tracker.process_transaction(event)
tracker.handle_minute_close(date)
msg = tracker.to_dict()
messages[date] = msg
messages = {}
for date, group in grouped_events:
tracker.set_date(date)
for event in group:
if event.type == zp.DATASOURCE_TYPE.TRADE:
tracker.process_trade(event)
elif event.type == zp.DATASOURCE_TYPE.BENCHMARK:
tracker.process_benchmark(event)
elif event.type == zp.DATASOURCE_TYPE.ORDER:
tracker.process_order(event)
elif event.type == zp.DATASOURCE_TYPE.TRANSACTION:
tracker.process_transaction(event)
tracker.handle_minute_close(date)
msg = tracker.to_dict()
messages[date] = msg
self.assertEquals(2, len(messages))
self.assertEquals(2, len(messages))
msg_1 = messages[foo_event_1.dt]
msg_2 = messages[foo_event_2.dt]
msg_1 = messages[foo_event_1.dt]
msg_2 = messages[foo_event_2.dt]
self.assertEquals(1, len(msg_1['minute_perf']['transactions']),
"The first message should contain one "
"transaction.")
# Check that transactions aren't emitted for previous events.
self.assertEquals(0, len(msg_2['minute_perf']['transactions']),
"The second message should have no "
"transactions.")
self.assertEquals(1, len(msg_1['minute_perf']['transactions']),
"The first message should contain one "
"transaction.")
# Check that transactions aren't emitted for previous events.
self.assertEquals(0, len(msg_2['minute_perf']['transactions']),
"The second message should have no "
"transactions.")
self.assertEquals(1, len(msg_1['minute_perf']['orders']),
"The first message should contain one orders.")
# Check that orders aren't emitted for previous events.
self.assertEquals(0, len(msg_2['minute_perf']['orders']),
"The second message should have no orders.")
self.assertEquals(1, len(msg_1['minute_perf']['orders']),
"The first message should contain one orders.")
# Check that orders aren't emitted for previous events.
self.assertEquals(0, len(msg_2['minute_perf']['orders']),
"The second message should have no orders.")
# Ensure that period_close moves through time.
# Also, ensure that the period_closes are the expected dts.
self.assertEquals(foo_event_1.dt,
msg_1['minute_perf']['period_close'])
self.assertEquals(foo_event_2.dt,
msg_2['minute_perf']['period_close'])
# Ensure that period_close moves through time.
# Also, ensure that the period_closes are the expected dts.
self.assertEquals(foo_event_1.dt,
msg_1['minute_perf']['period_close'])
self.assertEquals(foo_event_2.dt,
msg_2['minute_perf']['period_close'])
# In this test event1 transactions arrive on the first bar.
# This leads to no returns as the price is constant.
# Sharpe ratio cannot be computed and is None.
# In the second bar we can start establishing a sharpe ratio.
self.assertIsNone(msg_1['cumulative_risk_metrics']['sharpe'])
self.assertIsNotNone(msg_2['cumulative_risk_metrics']['sharpe'])
# In this test event1 transactions arrive on the first bar.
# This leads to no returns as the price is constant.
# Sharpe ratio cannot be computed and is None.
# In the second bar we can start establishing a sharpe ratio.
self.assertIsNone(msg_1['cumulative_risk_metrics']['sharpe'])
self.assertIsNotNone(msg_2['cumulative_risk_metrics']['sharpe'])
check_perf_tracker_serialization(tracker)
check_perf_tracker_serialization(tracker)
def test_close_position_event(self):
pt = perf.PositionTracker()
@@ -2021,9 +2020,12 @@ class TestPositionTracker(unittest.TestCase):
stats = [
'calculate_positions_value',
'_net_exposure',
'_gross_value',
'_gross_exposure',
'_short_value',
'_short_exposure',
'_shorts_count',
'_long_value',
'_long_exposure',
'_longs_count',
]
@@ -2033,15 +2035,82 @@ class TestPositionTracker(unittest.TestCase):
self.assertEquals(val, 0)
self.assertNotIsInstance(val, (bool, np.bool_))
def test_serializaition(self):
@with_environment()
def test_update_last_sale(self, env=None):
metadata = {1: {'asset_type': 'equity'},
2: {'asset_type': 'future',
'contract_multiplier': 1000}}
env.update_asset_finder(asset_metadata=metadata)
pt = perf.PositionTracker()
dt = pd.Timestamp("1984/03/06 3:00PM")
pos1 = perf.Position('AAPL', amount=np.float64(120.0),
pos1 = perf.Position(1, amount=np.float64(100.0),
last_sale_date=dt, last_sale_price=10)
pos2 = perf.Position(2, amount=np.float64(100.0),
last_sale_date=dt, last_sale_price=10)
pt.update_positions({1: pos1, 2: pos2})
event1 = Event({'sid': 1,
'price': 11,
'dt': dt})
event2 = Event({'sid': 2,
'price': 11,
'dt': dt})
# Check cash-adjustment return value
self.assertEqual(0, pt.update_last_sale(event1))
self.assertEqual(100000, pt.update_last_sale(event2))
@with_environment()
def test_position_values_and_exposures(self, env=None):
metadata = {1: {'asset_type': 'equity'},
2: {'asset_type': 'equity'},
3: {'asset_type': 'future',
'contract_multiplier': 1000},
4: {'asset_type': 'future',
'contract_multiplier': 1000}}
env.update_asset_finder(asset_metadata=metadata)
pt = perf.PositionTracker()
dt = pd.Timestamp("1984/03/06 3:00PM")
pos1 = perf.Position(1, amount=np.float64(10.0),
last_sale_date=dt, last_sale_price=10)
pos2 = perf.Position(2, amount=np.float64(-20.0),
last_sale_date=dt, last_sale_price=10)
pos3 = perf.Position(3, amount=np.float64(30.0),
last_sale_date=dt, last_sale_price=10)
pos4 = perf.Position(4, amount=np.float64(-40.0),
last_sale_date=dt, last_sale_price=10)
pt.update_positions({1: pos1, 2: pos2, 3: pos3, 4: pos4})
# Test long-only methods
self.assertEqual(100, pt._long_value())
self.assertEqual(100 + 300000, pt._long_exposure())
# Test short-only methods
self.assertEqual(-200, pt._short_value())
self.assertEqual(-200 - 400000, pt._short_exposure())
# Test gross and net values
self.assertEqual(100 + 200, pt._gross_value())
self.assertEqual(100 - 200, pt._net_value())
# Test gross and net exposures
self.assertEqual(100 + 200 + 300000 + 400000, pt._gross_exposure())
self.assertEqual(100 - 200 + 300000 - 400000, pt._net_exposure())
@with_environment()
def test_serialization(self, env=None):
metadata = {1: {'asset_type': 'equity'},
2: {'asset_type': 'future',
'contract_multiplier': 1000}}
env.update_asset_finder(asset_metadata=metadata)
pt = perf.PositionTracker()
dt = pd.Timestamp("1984/03/06 3:00PM")
pos1 = perf.Position(1, amount=np.float64(120.0),
last_sale_date=dt, last_sale_price=3.4)
pos2 = perf.Position('IBM', amount=np.float64(100.0),
pos2 = perf.Position(2, amount=np.float64(100.0),
last_sale_date=dt, last_sale_price=3.4)
pt.update_positions({'AAPL': pos1, 'IBM': pos2})
pt.update_positions({1: pos1, 2: pos2})
p_string = pickle.dumps(pt)
test = pickle.loads(p_string)
nt.assert_dict_equal(test._position_amounts, pt._position_amounts)
+55 -36
View File
@@ -6,6 +6,7 @@ from unittest import TestCase
from zipline.algorithm import TradingAlgorithm
from zipline.errors import TradingControlViolation
from zipline.sources import SpecificEquityTrades
from zipline.finance.trading import with_environment
from zipline.utils.test_utils import (
setup_logger, teardown_logger, security_list_copy, add_security_data)
from zipline.utils import factory
@@ -16,11 +17,11 @@ LEVERAGED_ETFS = load_from_directory('leveraged_etf_list')
class RestrictedAlgoWithCheck(TradingAlgorithm):
def initialize(self, sid):
def initialize(self, symbol):
self.rl = SecurityListSet(self.get_datetime)
self.set_do_not_order_list(self.rl.leveraged_etf_list)
self.order_count = 0
self.sid = sid
self.sid = self.symbol(symbol)
def handle_data(self, data):
if not self.order_count:
@@ -31,11 +32,11 @@ class RestrictedAlgoWithCheck(TradingAlgorithm):
class RestrictedAlgoWithoutCheck(TradingAlgorithm):
def initialize(self, sid):
def initialize(self, symbol):
self.rl = SecurityListSet(self.get_datetime)
self.set_do_not_order_list(self.rl.leveraged_etf_list)
self.order_count = 0
self.sid = sid
self.sid = self.symbol(symbol)
def handle_data(self, data):
self.order(self.sid, 100)
@@ -43,11 +44,11 @@ class RestrictedAlgoWithoutCheck(TradingAlgorithm):
class IterateRLAlgo(TradingAlgorithm):
def initialize(self, sid):
def initialize(self, symbol):
self.rl = SecurityListSet(self.get_datetime)
self.set_do_not_order_list(self.rl.leveraged_etf_list)
self.order_count = 0
self.sid = sid
self.sid = self.symbol(symbol)
self.found = False
def handle_data(self, data):
@@ -58,12 +59,18 @@ class IterateRLAlgo(TradingAlgorithm):
class SecurityListTestCase(TestCase):
def setUp(self):
@with_environment()
def setUp(self, env=None):
self.extra_knowledge_date = \
datetime(2015, 1, 27, 0, 0, tzinfo=pytz.utc)
self.trading_day_before_first_kd = datetime(
2015, 1, 23, 0, 0, tzinfo=pytz.utc)
env.update_asset_finder(
clear_metadata=True,
identifiers=["BZQ", "URTY", "JFT", "AAPL", "GOOG"]
)
setup_logger(self)
def tearDown(self):
@@ -81,11 +88,12 @@ class SecurityListTestCase(TestCase):
sim_params
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = IterateRLAlgo(sid='BZQ', sim_params=sim_params)
algo = IterateRLAlgo(symbol='BZQ', sim_params=sim_params)
algo.run(self.source)
self.assertTrue(algo.found)
def test_security_list(self):
@with_environment()
def test_security_list(self, env=None):
# set the knowledge date to the first day of the
# leveraged etf knowledge date.
@@ -94,27 +102,43 @@ class SecurityListTestCase(TestCase):
rl = SecurityListSet(get_datetime)
# assert that a sample from the leveraged list are in restricted
self.assertIn("BZQ", rl.leveraged_etf_list)
self.assertIn("URTY", rl.leveraged_etf_list)
self.assertIn("JFT", rl.leveraged_etf_list)
should_exist = [
asset.sid for asset in
[env.asset_finder.lookup_symbol(
symbol,
as_of_date=self.extra_knowledge_date)
for symbol in ["BZQ", "URTY", "JFT"]]
]
for sid in should_exist:
self.assertIn(sid, rl.leveraged_etf_list)
# assert that a sample of allowed stocks are not in restricted
# AAPL
self.assertNotIn("AAPL", rl.leveraged_etf_list)
# GOOG
self.assertNotIn("GOOG", rl.leveraged_etf_list)
shouldnt_exist = [
asset.sid for asset in
[env.asset_finder.lookup_symbol(
symbol,
as_of_date=self.extra_knowledge_date)
for symbol in ["AAPL", "GOOG"]]
]
for sid in shouldnt_exist:
self.assertNotIn(sid, rl.leveraged_etf_list)
def test_security_add(self):
@with_environment()
def test_security_add(self, env=None):
def get_datetime():
return datetime(2015, 1, 27, tzinfo=pytz.utc)
with security_list_copy():
add_security_data(['AAPL', 'GOOG'], [])
rl = SecurityListSet(get_datetime)
self.assertIn("AAPL", rl.leveraged_etf_list)
self.assertIn("GOOG", rl.leveraged_etf_list)
self.assertIn("BZQ", rl.leveraged_etf_list)
self.assertIn("URTY", rl.leveraged_etf_list)
should_exist = [
asset.sid for asset in
[env.asset_finder.lookup_symbol(
symbol,
as_of_date=self.extra_knowledge_date
) for symbol in ["AAPL", "GOOG", "BZQ", "URTY"]]
]
for sid in should_exist:
self.assertIn(sid, rl.leveraged_etf_list)
def test_security_add_delete(self):
with security_list_copy():
@@ -138,7 +162,7 @@ class SecurityListTestCase(TestCase):
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = RestrictedAlgoWithCheck(sid='BZQ', sim_params=sim_params)
algo = RestrictedAlgoWithCheck(symbol='BZQ', sim_params=sim_params)
algo.run(self.source)
def test_algo_without_rl_violation(self):
@@ -153,7 +177,7 @@ class SecurityListTestCase(TestCase):
sim_params
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = RestrictedAlgoWithoutCheck(sid='AAPL', sim_params=sim_params)
algo = RestrictedAlgoWithoutCheck(symbol='AAPL', sim_params=sim_params)
algo.run(self.source)
def test_algo_with_rl_violation(self):
@@ -169,10 +193,7 @@ class SecurityListTestCase(TestCase):
)
self.source = SpecificEquityTrades(event_list=trade_history)
self.df_source, self.df = \
factory.create_test_df_source(sim_params)
algo = RestrictedAlgoWithoutCheck(sid='BZQ', sim_params=sim_params)
algo = RestrictedAlgoWithoutCheck(symbol='BZQ', sim_params=sim_params)
with self.assertRaises(TradingControlViolation) as ctx:
algo.run(self.source)
@@ -189,10 +210,7 @@ class SecurityListTestCase(TestCase):
)
self.source = SpecificEquityTrades(event_list=trade_history)
self.df_source, self.df = \
factory.create_test_df_source(sim_params)
algo = RestrictedAlgoWithoutCheck(sid='JFT', sim_params=sim_params)
algo = RestrictedAlgoWithoutCheck(symbol='JFT', sim_params=sim_params)
with self.assertRaises(TradingControlViolation) as ctx:
algo.run(self.source)
@@ -211,7 +229,7 @@ class SecurityListTestCase(TestCase):
sim_params
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = RestrictedAlgoWithoutCheck(sid='BZQ', sim_params=sim_params)
algo = RestrictedAlgoWithoutCheck(symbol='BZQ', sim_params=sim_params)
with self.assertRaises(TradingControlViolation) as ctx:
algo.run(self.source)
@@ -238,7 +256,7 @@ class SecurityListTestCase(TestCase):
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = RestrictedAlgoWithoutCheck(
sid='BZQ', sim_params=sim_params)
symbol='BZQ', sim_params=sim_params)
with self.assertRaises(TradingControlViolation) as ctx:
algo.run(self.source)
@@ -261,7 +279,8 @@ class SecurityListTestCase(TestCase):
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = RestrictedAlgoWithoutCheck(
sid='BZQ', sim_params=sim_params)
symbol='BZQ', sim_params=sim_params
)
algo.run(self.source)
def test_algo_with_rl_violation_after_add(self):
@@ -278,7 +297,7 @@ class SecurityListTestCase(TestCase):
)
self.source = SpecificEquityTrades(event_list=trade_history)
algo = RestrictedAlgoWithoutCheck(
sid='AAPL', sim_params=sim_params)
symbol='AAPL', sim_params=sim_params)
with self.assertRaises(TradingControlViolation) as ctx:
algo.run(self.source)
+33 -18
View File
@@ -26,6 +26,7 @@ from zipline.sources import (DataFrameSource,
DataPanelSource,
RandomWalkSource)
from zipline.utils import tradingcalendar as calendar_nyse
from zipline.finance.trading import with_environment
class TestDataFrameSource(TestCase):
@@ -62,7 +63,8 @@ class TestDataFrameSource(TestCase):
self.assertTrue(isinstance(event['volume'], int))
self.assertTrue(isinstance(event['arbitrary'], float))
def test_yahoo_bars_to_panel_source(self):
@with_environment()
def test_yahoo_bars_to_panel_source(self, env=None):
stocks = ['AAPL', 'GE']
start = pd.datetime(1993, 1, 1, 0, 0, 0, 0, pytz.utc)
end = pd.datetime(2002, 1, 1, 0, 0, 0, 0, pytz.utc)
@@ -74,45 +76,58 @@ class TestDataFrameSource(TestCase):
check_fields = ['sid', 'open', 'high', 'low', 'close',
'volume', 'price']
source = DataPanelSource(data)
stocks_iter = cycle(stocks)
sids = [
asset.sid for asset in
[env.asset_finder.lookup_symbol(symbol, as_of_date=end)
for symbol in stocks]
]
stocks_iter = cycle(sids)
for event in source:
for check_field in check_fields:
self.assertIn(check_field, event)
self.assertTrue(isinstance(event['volume'], (integer_types)))
self.assertEqual(next(stocks_iter), event['sid'])
def test_nan_filter_dataframe(self):
@with_environment()
def test_nan_filter_dataframe(self, env=None):
env.update_asset_finder(identifiers=[4, 5])
dates = pd.date_range('1/1/2000', periods=2, freq='B', tz='UTC')
df = pd.DataFrame(np.random.randn(2, 2),
index=dates,
columns=['A', 'B'])
df.loc[dates[0], 'A'] = np.nan # should be filtered
df.loc[dates[1], 'B'] = np.nan # should not be filtered
columns=[4, 5])
# should be filtered
df.loc[dates[0], 4] = np.nan
# should not be filtered, should have been ffilled
df.loc[dates[1], 5] = np.nan
source = DataFrameSource(df)
event = next(source)
self.assertEqual('B', event.sid)
self.assertEqual(5, event.sid)
event = next(source)
self.assertEqual('A', event.sid)
self.assertEqual(4, event.sid)
event = next(source)
self.assertEqual('B', event.sid)
self.assertTrue(np.isnan(event.price))
self.assertEqual(5, event.sid)
self.assertFalse(np.isnan(event.price))
def test_nan_filter_panel(self):
@with_environment()
def test_nan_filter_panel(self, env=None):
env.update_asset_finder(identifiers=[4, 5])
dates = pd.date_range('1/1/2000', periods=2, freq='B', tz='UTC')
df = pd.Panel(np.random.randn(2, 2, 2),
major_axis=dates,
items=['A', 'B'],
items=[4, 5],
minor_axis=['price', 'volume'])
df.loc['A', dates[0], 'price'] = np.nan # should be filtered
df.loc['B', dates[1], 'price'] = np.nan # should not be filtered
# should be filtered
df.loc[4, dates[0], 'price'] = np.nan
# should not be filtered, should have been ffilled
df.loc[5, dates[1], 'price'] = np.nan
source = DataPanelSource(df)
event = next(source)
self.assertEqual('B', event.sid)
self.assertEqual(5, event.sid)
event = next(source)
self.assertEqual('A', event.sid)
self.assertEqual(4, event.sid)
event = next(source)
self.assertEqual('B', event.sid)
self.assertTrue(np.isnan(event.price))
self.assertEqual(5, event.sid)
self.assertFalse(np.isnan(event.price))
class TestRandomWalkSource(TestCase):