mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-30 22:18:31 +08:00
TST: Reconciles tests with asset management system
This commit is contained in:
+147
-42
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user