Skip to content

Commit

Permalink
ENH: Send transactions and orders as standalone events.
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
Eddie Hebert committed Apr 14, 2013
1 parent cfbbbe2 commit 35f57ad
Show file tree
Hide file tree
Showing 12 changed files with 538 additions and 345 deletions.
177 changes: 84 additions & 93 deletions tests/finance/test_slippage.py

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions tests/test_algorithm_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ def handle_data(self, data):

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):
Expand Down
41 changes: 24 additions & 17 deletions tests/test_finance.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@
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,
Expand Down Expand Up @@ -160,7 +159,12 @@ def test_sim_params_days_in_period(self):
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)

Expand Down Expand Up @@ -205,7 +209,8 @@ def test_partially_filled_orders(self):
@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,
Expand All @@ -215,8 +220,8 @@ def test_collapsing_orders(self):
'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)

Expand All @@ -228,8 +233,8 @@ def test_collapsing_orders(self):
'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)

Expand All @@ -242,8 +247,8 @@ def test_collapsing_orders(self):
'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)

Expand Down Expand Up @@ -285,7 +290,7 @@ def transaction_sim(self, **params):

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
Expand All @@ -311,7 +316,7 @@ def transaction_sim(self, **params):
'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
Expand All @@ -322,7 +327,7 @@ def transaction_sim(self, **params):
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]
Expand All @@ -340,10 +345,12 @@ def transaction_sim(self, **params):
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:
Expand All @@ -364,7 +371,7 @@ def transaction_sim(self, **params):
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))
Loading

0 comments on commit 35f57ad

Please sign in to comment.