ENH: Send transactions and orders as standalone events.

- Add transaction and order types
- Move TransactionSimulator from trading.py to tradesimulation.py
  (only used by other members of the tradesimulation module)
- Make Transaction an independent event, like dividend
- Add Blotter class.
- Flatten the transaction events to be independent of trade bar events
- Make orders into events that reach performance (need to add
handling)
- Issue IDs to orders and tracking each transaction's order id.
- Make volume share slippage fill orders independently, rather than
  aggregating them into a single transaction.
- Perf tracker holds orders, serializes them with transactions.
- Order state defined and maintained by order class.
- Minutely emission of orders based on last_modified date.
This commit is contained in:
Eddie Hebert
2013-04-14 18:59:57 -04:00
parent cfbbbe2f1c
commit 35f57ada3e
12 changed files with 531 additions and 338 deletions
+84 -93
View File
@@ -24,17 +24,15 @@ from unittest import TestCase
from zipline.finance.slippage import VolumeShareSlippage
from zipline.protocol import Event
from zipline.protocol import Event, DATASOURCE_TYPE
from zipline.gens.tradesimulation import Order
class SlippageTestCase(TestCase):
def test_volume_share_slippage(self):
event = Event(
{'volume': 200,
'TRANSACTION': None,
'type': 4,
'price': 3.0,
'datetime': datetime.datetime(
@@ -51,26 +49,31 @@ class SlippageTestCase(TestCase):
slippage_model = VolumeShareSlippage()
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
'filled': 0,
'sid': 133})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
event,
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.01875),
'dt': datetime.datetime(
2006, 1, 5, 14, 31, tzinfo=pytz.utc),
'amount': int(50),
'sid': int(133),
'commission': None
'commission': None,
'type': DATASOURCE_TYPE.TRANSACTION,
'order_id': open_orders[0].id
}
self.assertIsNotNone(txn)
@@ -87,46 +90,46 @@ class SlippageTestCase(TestCase):
# long, does not trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
'filled': 0,
'sid': 133,
'limit': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[2],
open_orders
)
expected_txn = {}
self.assertIsNone(txn)
self.assertEquals(len(txns), 0)
# long, does trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
'filled': 0,
'sid': 133,
'limit': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[3],
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.500875),
'dt': datetime.datetime(
2006, 1, 5, 14, 34, tzinfo=pytz.utc),
'amount': int(100),
'sid': int(133)
'sid': int(133),
'order_id': open_orders[0].id
}
self.assertIsNotNone(txn)
@@ -136,40 +139,43 @@ class SlippageTestCase(TestCase):
# short, does not trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': -100,
'filled': 0,
'sid': 133,
'limit': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[0],
open_orders
)
expected_txn = {}
self.assertIsNone(txn)
self.assertEquals(len(txns), 0)
# short, does trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': -100,
'filled': 0,
'sid': 133,
'limit': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[1],
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.499125),
'dt': datetime.datetime(
@@ -190,89 +196,91 @@ class SlippageTestCase(TestCase):
# long, does not trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
'filled': 0,
'sid': 133,
'stop': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[2],
open_orders
)
expected_txn = {}
self.assertIsNone(txn)
self.assertEquals(len(txns), 0)
# long, does trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
'filled': 0,
'sid': 133,
'stop': 3.6})
]}
'stop': 3.6
})
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[3],
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.500875),
'dt': datetime.datetime(
2006, 1, 5, 14, 34, tzinfo=pytz.utc),
'amount': int(100),
'sid': int(133)
'sid': int(133),
'order_id': open_orders[0].id
}
self.assertIsNotNone(txn)
for key, value in expected_txn.items():
self.assertEquals(value, txn[key])
# short, does not trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': -100,
'filled': 0,
'sid': 133,
'stop': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[0],
open_orders
)
expected_txn = {}
self.assertIsNone(txn)
self.assertEquals(len(txns), 0)
# short, does trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': -100,
'filled': 0,
'sid': 133,
'stop': 3.4})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[1],
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.499125),
'dt': datetime.datetime(
@@ -281,8 +289,6 @@ class SlippageTestCase(TestCase):
'sid': int(133)
}
self.assertIsNotNone(txn)
for key, value in expected_txn.items():
self.assertEquals(value, txn[key])
@@ -293,7 +299,7 @@ class SlippageTestCase(TestCase):
# long, does not trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
@@ -301,29 +307,25 @@ class SlippageTestCase(TestCase):
'sid': 133,
'stop': 4.0,
'limit': 3.0})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[2],
open_orders
)
expected_txn = {}
self.assertEquals(len(txns), 0)
self.assertIsNone(txn)
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[3],
open_orders
)
expected_txn = {}
self.assertIsNone(txn)
self.assertEquals(len(txns), 0)
# long, does trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': 100,
@@ -331,22 +333,23 @@ class SlippageTestCase(TestCase):
'sid': 133,
'stop': 4.0,
'limit': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[2],
open_orders
)
expected_txn = {}
self.assertEquals(len(txns), 0)
self.assertIsNone(txn)
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[3],
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.500875),
'dt': datetime.datetime(
@@ -355,14 +358,12 @@ class SlippageTestCase(TestCase):
'sid': int(133)
}
self.assertIsNotNone(txn)
for key, value in expected_txn.items():
self.assertEquals(value, txn[key])
# short, does not trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': -100,
@@ -370,29 +371,25 @@ class SlippageTestCase(TestCase):
'sid': 133,
'stop': 3.0,
'limit': 4.0})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[0],
open_orders
)
expected_txn = {}
self.assertEquals(len(txns), 0)
self.assertIsNone(txn)
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[1],
open_orders
)
expected_txn = {}
self.assertIsNone(txn)
self.assertEquals(len(txns), 0)
# short, does trade
open_orders = {133: [
open_orders = [
Order(**{
'dt': datetime.datetime(2006, 1, 5, 14, 30, tzinfo=pytz.utc),
'amount': -100,
@@ -400,22 +397,23 @@ class SlippageTestCase(TestCase):
'sid': 133,
'stop': 3.0,
'limit': 3.5})
]}
]
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[0],
open_orders
)
expected_txn = {}
self.assertEquals(len(txns), 0)
self.assertIsNone(txn)
txn = slippage_model.simulate(
txns = slippage_model.simulate(
events[1],
open_orders
)
self.assertEquals(len(txns), 1)
txn = txns[0]
expected_txn = {
'price': float(3.499125),
'dt': datetime.datetime(
@@ -424,8 +422,6 @@ class SlippageTestCase(TestCase):
'sid': int(133)
}
self.assertIsNotNone(txn)
for key, value in expected_txn.items():
self.assertEquals(value, txn[key])
@@ -434,7 +430,6 @@ class SlippageTestCase(TestCase):
events = [
Event({
'volume': 2000,
'TRANSACTION': None,
'type': 4,
'price': 3.0,
'datetime': datetime.datetime(
@@ -450,7 +445,6 @@ class SlippageTestCase(TestCase):
}),
Event({
'volume': 2000,
'TRANSACTION': None,
'type': 4,
'price': 3.5,
'datetime': datetime.datetime(
@@ -466,7 +460,6 @@ class SlippageTestCase(TestCase):
}),
Event({
'volume': 2000,
'TRANSACTION': None,
'type': 4,
'price': 4.0,
'datetime': datetime.datetime(
@@ -482,7 +475,6 @@ class SlippageTestCase(TestCase):
}),
Event({
'volume': 2000,
'TRANSACTION': None,
'type': 4,
'price': 3.5,
'datetime': datetime.datetime(
@@ -498,7 +490,6 @@ class SlippageTestCase(TestCase):
}),
Event({
'volume': 2000,
'TRANSACTION': None,
'type': 4,
'price': 3.0,
'datetime': datetime.datetime(
+6 -4
View File
@@ -66,10 +66,12 @@ class TestAlgo(TradingAlgorithm):
self.ordered = True
self.asserter.assertGreaterEqual(
self.latest_date,
self.slippage.latest_date
)
else:
self.asserter.assertGreaterEqual(
self.latest_date,
self.slippage.latest_date
)
class AlgorithmGeneratorTestCase(TestCase):
+24 -17
View File
@@ -31,13 +31,12 @@ from nose.tools import timed
import zipline.utils.factory as factory
import zipline.utils.simfactory as simfactory
from zipline.gens.tradesimulation import Order
from zipline.gens.tradesimulation import Order, Blotter
import zipline.finance.trading as trading
from zipline.finance.trading import SimulationParameters
from zipline.finance.performance import PerformanceTracker
from zipline.finance.trading import TransactionSimulator
from zipline.utils.test_utils import(
setup_logger,
teardown_logger,
@@ -160,7 +159,12 @@ class FinanceTestCase(TestCase):
def test_full_zipline(self):
#provide enough trades to ensure all orders are filled.
self.zipline_test_config['order_count'] = 100
self.zipline_test_config['trade_count'] = 200
# making a small order amount, so that each order is filled
# in a single transaction, and txn_count == order_count.
self.zipline_test_config['order_amount'] = 25
# No transactions can be filled on the first trade, so
# we have one extra trade to ensure all orders are filled.
self.zipline_test_config['trade_count'] = 101
zipline = simfactory.create_test_zipline(**self.zipline_test_config)
assert_single_position(self, zipline)
@@ -205,7 +209,8 @@ class FinanceTestCase(TestCase):
@timed(DEFAULT_TIMEOUT)
def test_collapsing_orders(self):
# create a scenario where order.amount <<< trade.volume
# to test that several orders can be covered properly by one trade.
# to test that several orders can be covered properly by one trade,
# but are represented by multiple transactions.
params1 = {
'trade_count': 6,
'trade_amount': 100,
@@ -215,8 +220,8 @@ class FinanceTestCase(TestCase):
'order_interval': timedelta(minutes=1),
# because we placed an orders totaling less than 25% of one trade
# the simulator should produce just one transaction.
'expected_txn_count': 1,
'expected_txn_volume': 24 * 1
'expected_txn_count': 24,
'expected_txn_volume': 24
}
self.transaction_sim(**params1)
@@ -228,8 +233,8 @@ class FinanceTestCase(TestCase):
'order_count': 24,
'order_amount': -1,
'order_interval': timedelta(minutes=1),
'expected_txn_count': 1,
'expected_txn_volume': 24 * -1
'expected_txn_count': 24,
'expected_txn_volume': -24
}
self.transaction_sim(**params2)
@@ -242,8 +247,8 @@ class FinanceTestCase(TestCase):
'order_count': 24,
'order_amount': 1,
'order_interval': timedelta(minutes=1),
'expected_txn_count': 1,
'expected_txn_volume': 24 * 1
'expected_txn_count': 24,
'expected_txn_volume': 24
}
self.transaction_sim(**params3)
@@ -285,7 +290,7 @@ class FinanceTestCase(TestCase):
sid = 1
sim_params = factory.create_simulation_parameters()
trade_sim = TransactionSimulator()
blotter = Blotter()
price = [10.1] * trade_count
volume = [100] * trade_count
start_date = sim_params.first_open
@@ -311,7 +316,7 @@ class FinanceTestCase(TestCase):
'dt': order_date
})
trade_sim.place_order(order)
blotter.place_order(order)
order_date = order_date + order_interval
# move after market orders to just after market next
@@ -322,7 +327,7 @@ class FinanceTestCase(TestCase):
order_date = order_date.replace(hour=14, minute=30)
# there should now be one open order list stored under the sid
oo = trade_sim.open_orders
oo = blotter.open_orders
self.assertEqual(len(oo), 1)
self.assertTrue(sid in oo)
order_list = oo[sid]
@@ -340,10 +345,12 @@ class FinanceTestCase(TestCase):
for dt, trades in itertools.groupby(generated_trades,
operator.attrgetter('dt')):
for trade in trades:
trade_sim.update(trade)
if trade.TRANSACTION:
transactions.append(trade.TRANSACTION)
txns = blotter.process_trade(trade)
for txn in txns:
transactions.append(txn)
tracker.process_event(txn)
tracker.process_event(trade)
if complete_fill:
@@ -364,7 +371,7 @@ class FinanceTestCase(TestCase):
self.assertEqual(total_volume, cumulative_pos.amount)
# the open orders should now be empty
oo = trade_sim.open_orders
oo = blotter.open_orders
self.assertTrue(sid in oo)
order_list = oo[sid]
self.assertEqual(0, len(order_list))
+87 -51
View File
@@ -24,11 +24,13 @@ from operator import attrgetter
import zipline.utils.factory as factory
import zipline.finance.performance as perf
from zipline.finance.slippage import Transaction
from zipline.finance.slippage import Transaction, create_transaction
from zipline.gens.composites import date_sorted_sources
from zipline.finance.trading import SimulationParameters
from zipline.gens.tradesimulation import Order
import zipline.finance.trading as trading
from zipline.protocol import DATASOURCE_TYPE
from zipline.utils.factory import create_random_simulation_parameters
onesec = datetime.timedelta(seconds=1)
@@ -36,6 +38,10 @@ oneday = datetime.timedelta(days=1)
tradingday = datetime.timedelta(hours=6, minutes=30)
def create_txn(sid, price, amount, dt):
return create_transaction(sid, amount, price, dt, "fakeuid")
class TestDividendPerformance(unittest.TestCase):
def setUp(self):
@@ -78,8 +84,8 @@ class TestDividendPerformance(unittest.TestCase):
events[2].dt
)
txn = factory.create_txn(1, 10.0, 100, events[0].dt)
events[0].TRANSACTION = txn
txn = create_txn(1, 10.0, 100, events[0].dt)
events.insert(0, txn)
events.insert(1, dividend)
perf_tracker = perf.PerformanceTracker(self.sim_params)
transformed_events = list(perf_tracker.transform(
@@ -136,8 +142,8 @@ class TestDividendPerformance(unittest.TestCase):
)
events.insert(1, dividend)
txn = factory.create_txn(1, 10.0, 100, events[3].dt)
events[3].TRANSACTION = txn
txn = create_txn(1, 10.0, 100, events[3].dt)
events.insert(4, txn)
perf_tracker = perf.PerformanceTracker(self.sim_params)
transformed_events = list(perf_tracker.transform(
((event.dt, [event]) for event in events))
@@ -183,11 +189,11 @@ class TestDividendPerformance(unittest.TestCase):
events[3].dt
)
buy_txn = factory.create_txn(1, 10.0, 100, events[0].dt)
events[0].TRANSACTION = buy_txn
sell_txn = factory.create_txn(1, 10.0, -100, events[2].dt)
events[2].TRANSACTION = sell_txn
events.insert(1, dividend)
buy_txn = create_txn(1, 10.0, 100, events[0].dt)
events.insert(1, buy_txn)
sell_txn = create_txn(1, 10.0, -100, events[3].dt)
events.insert(4, sell_txn)
events.insert(0, dividend)
perf_tracker = perf.PerformanceTracker(self.sim_params)
transformed_events = list(perf_tracker.transform(
((event.dt, [event]) for event in events))
@@ -233,10 +239,10 @@ class TestDividendPerformance(unittest.TestCase):
events[5].dt
)
buy_txn = factory.create_txn(1, 10.0, 100, events[1].dt)
events[1].TRANSACTION = buy_txn
sell_txn = factory.create_txn(1, 10.0, -100, events[2].dt)
events[2].TRANSACTION = sell_txn
buy_txn = create_txn(1, 10.0, 100, events[1].dt)
events.insert(2, buy_txn)
sell_txn = create_txn(1, 10.0, -100, events[3].dt)
events.insert(4, sell_txn)
events.insert(1, dividend)
perf_tracker = perf.PerformanceTracker(self.sim_params)
transformed_events = list(perf_tracker.transform(
@@ -280,11 +286,11 @@ class TestDividendPerformance(unittest.TestCase):
10.00,
events[0].dt,
events[1].dt,
events[-1].dt + 10*oneday
events[-1].dt + 10 * oneday
)
buy_txn = factory.create_txn(1, 10.0, 100, events[1].dt)
events[1].TRANSACTION = buy_txn
buy_txn = create_txn(1, 10.0, 100, events[1].dt)
events.insert(2, buy_txn)
events.insert(1, dividend)
perf_tracker = perf.PerformanceTracker(self.sim_params)
transformed_events = list(perf_tracker.transform(
@@ -334,8 +340,8 @@ class TestDividendPerformance(unittest.TestCase):
events[2].dt
)
txn = factory.create_txn(1, 10.0, -100, self.dt+oneday)
events[0].TRANSACTION = txn
txn = create_txn(1, 10.0, -100, self.dt + oneday)
events.insert(1, txn)
events.insert(0, dividend)
perf_tracker = perf.PerformanceTracker(self.sim_params)
transformed_events = list(perf_tracker.transform(
@@ -431,7 +437,7 @@ class TestPositionPerformance(unittest.TestCase):
self.sim_params
)
txn = factory.create_txn(1, 10.0, 100, self.dt + onesec)
txn = create_txn(1, 10.0, 100, self.dt + onesec)
pp = perf.PerformancePeriod(1000.0)
pp.execute_transaction(txn)
@@ -502,7 +508,7 @@ single short-sale transaction"""
trades_1 = trades[:-2]
txn = factory.create_txn(1, 10.0, -100, self.dt + onesec)
txn = create_txn(1, 10.0, -100, self.dt + onesec)
pp = perf.PerformancePeriod(1000.0)
pp.execute_transaction(txn)
@@ -690,14 +696,14 @@ trade after cover"""
self.sim_params
)
short_txn = factory.create_txn(
short_txn = create_txn(
1,
10.0,
-100,
self.dt + onesec
)
cover_txn = factory.create_txn(1, 7.0, 100, self.dt + onesec * 6)
cover_txn = create_txn(1, 7.0, 100, self.dt + onesec * 6)
pp = perf.PerformancePeriod(1000.0)
pp.execute_transaction(short_txn)
@@ -805,7 +811,7 @@ shares in position"
400
)
saleTxn = factory.create_txn(
saleTxn = create_txn(
1,
10.0,
-100,
@@ -871,6 +877,11 @@ shares in position"
class TestPerformanceTracker(unittest.TestCase):
def setUp(self):
self.sim_params, self.dt, self.end_dt = \
create_random_simulation_parameters()
NumDaysToDelete = collections.namedtuple(
'NumDaysToDelete', ('start', 'middle', 'end'))
@@ -984,11 +995,15 @@ class TestPerformanceTracker(unittest.TestCase):
events = date_sorted_sources(trade_history, trade_history2)
events = [self.event_with_txn(event, trade_history[0].dt)
for event in events]
events = [event for event in
self.trades_with_txns(events, trade_history[0].dt)]
# Extract events with transactions to use for verification.
events_with_txns = [event for event in events if event.TRANSACTION]
txns = [event for event in
events if event.type == DATASOURCE_TYPE.TRANSACTION]
orders = [event for event in
events if event.type == DATASOURCE_TYPE.ORDER]
perf_messages = \
[msg for date, snapshot in
@@ -1002,10 +1017,11 @@ class TestPerformanceTracker(unittest.TestCase):
perf_messages.extend(end_perf_messages)
#we skip two trades, to test case of None transaction
self.assertEqual(perf_tracker.txn_count, len(events_with_txns))
self.assertEqual(perf_tracker.txn_count, len(txns))
self.assertEqual(perf_tracker.txn_count, len(orders))
cumulative_pos = perf_tracker.cumulative_performance.positions[sid]
expected_size = len(events_with_txns) / 2 * -25
expected_size = len(txns) / 2 * -25
self.assertEqual(cumulative_pos.amount, expected_size)
self.assertEqual(perf_tracker.last_close,
@@ -1014,22 +1030,30 @@ class TestPerformanceTracker(unittest.TestCase):
self.assertEqual(len(perf_messages),
sim_params.days_in_period)
def event_with_txn(self, event, no_txn_dt):
#create a transaction for all but
#first trade in each sid, to simulate None transaction
if event.dt != no_txn_dt:
txn = Transaction(**{
'sid': event.sid,
'amount': -25,
'dt': event.dt,
'price': 10.0,
'commission': 0.50
})
else:
txn = None
event['TRANSACTION'] = txn
def trades_with_txns(self, events, no_txn_dt):
for event in events:
return event
#create a transaction for all but
#first trade in each sid, to simulate None transaction
if event.dt != no_txn_dt:
order = Order(**{
'sid': event.sid,
'amount': -25,
'dt': event.dt
})
yield order
yield event
txn = Transaction(**{
'sid': event.sid,
'amount': -25,
'dt': event.dt,
'price': 10.0,
'commission': 0.50,
'order_id': order.id
})
yield txn
else:
yield event
@trading.use_environment(trading.TradingEnvironment())
def test_minute_tracker(self):
@@ -1047,13 +1071,17 @@ class TestPerformanceTracker(unittest.TestCase):
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,
'amount': -25,
'dt': foo_event_1.dt
})
bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt)
txn = Transaction(sid=foo_event_1.sid,
amount=-25,
dt=foo_event_1.dt,
price=10.0,
commission=0.50)
foo_event_1.TRANSACTION = txn
txn_event_1 = Transaction(sid=foo_event_1.sid,
amount=-25,
dt=foo_event_1.dt,
price=10.0,
commission=0.50)
foo_event_2 = factory.create_trade(
'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1))
@@ -1062,13 +1090,15 @@ class TestPerformanceTracker(unittest.TestCase):
events = [
foo_event_1,
order_event_1,
txn_event_1,
bar_event_1,
foo_event_2,
bar_event_2
]
import operator
messages = {date: snapshot[0].perf_messages[0] for date, snapshot in
messages = {date: snapshot[-1].perf_messages[0] for date, snapshot in
tracker.transform(
itertools.groupby(
events,
@@ -1085,6 +1115,12 @@ class TestPerformanceTracker(unittest.TestCase):
self.assertEquals(0, len(msg_2['intraday_perf']['transactions']),
"The second message should have no transactions.")
self.assertEquals(1, len(msg_1['intraday_perf']['orders']),
"The first message should contain one orders.")
# Check that orders aren't emitted for previous events.
self.assertEquals(0, len(msg_2['intraday_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,