Merge pull request #50 from quantopian/fawce_alpha1

Fawce alpha1
This commit is contained in:
Stephen Diehl
2012-05-21 07:15:37 -07:00
13 changed files with 173 additions and 65 deletions
+4 -4
View File
@@ -224,11 +224,11 @@ class FinanceTestCase(TestCase):
"Portfolio should have one position."
)
SID = self.zipline_test_config['sid']
sid = self.zipline_test_config['sid']
self.assertEqual(
zipline.get_positions()[SID]['sid'],
SID,
"Portfolio should have one position in " + str(SID)
zipline.get_positions()[sid]['sid'],
sid,
"Portfolio should have one position in " + str(sid)
)
self.assertEqual(
+90
View File
@@ -0,0 +1,90 @@
from datetime import timedelta
from collections import defaultdict
from unittest2 import TestCase
import zipline.utils.factory as factory
from zipline.finance.vwap import DailyVWAP, VWAPTransform
from zipline.finance.returns import ReturnsFromPriorClose
from zipline.finance.movingaverage import MovingAverage
from zipline.lines import SimulatedTrading
from zipline.core.devsimulator import AddressAllocator
allocator = AddressAllocator(1000)
class ZiplineWithTransformsTestCase(TestCase):
leased_sockets = defaultdict(list)
def setUp(self):
# skip ahead 100 spots
allocator.lease(100)
self.trading_environment = factory.create_trading_environment()
self.zipline_test_config = {
'allocator':allocator,
'sid':133
}
def test_vwap_tnfm(self):
zipline = SimulatedTrading.create_test_zipline(
**self.zipline_test_config
)
vwap = VWAPTransform("vwap_10", daycount=10)
zipline.add_transform(vwap)
zipline.simulate(blocking=True)
self.assertTrue(zipline.sim.ready())
self.assertFalse(zipline.sim.exception)
class FinanceTransformsTestCase(TestCase):
def setUp(self):
self.trading_environment = factory.create_trading_environment()
def test_vwap(self):
trade_history = factory.create_trade_history(
133,
[10.0, 10.0, 10.0, 11.0],
[100, 100, 100, 300],
timedelta(days=1),
self.trading_environment
)
vwap = DailyVWAP(days=2)
for trade in trade_history:
vwap.update(trade)
self.assertEqual(vwap.vwap, 10.75)
def test_returns(self):
trade_history = factory.create_trade_history(
133,
[10.0, 10.0, 10.0, 11.0],
[100, 100, 100, 300],
timedelta(days=1),
self.trading_environment
)
returns = ReturnsFromPriorClose()
for trade in trade_history:
returns.update(trade)
self.assertEqual(returns.returns, .1)
def test_moving_average(self):
trade_history = factory.create_trade_history(
133,
[10.0, 10.0, 10.0, 11.0],
[100, 100, 100, 300],
timedelta(days=1),
self.trading_environment
)
ma = MovingAverage(days=2)
for trade in trade_history:
ma.update(trade)
self.assertEqual(ma.average, 10.5)
+1 -1
View File
@@ -17,7 +17,7 @@ class DataSource(Component):
converting to a dict, and calling send(map).
Every datasource has a dict property to hold filters::
- key -- name of the filter, e.g. SID
- key -- name of the filter, e.g. sid
- value -- a primitive representing the filter. e.g. a list of ints.
Modify the datasource's filters via the set_filter(name, value)
-2
View File
@@ -1,7 +1,5 @@
from feed import Feed
import zipline.protocol as zp
from zipline.protocol import COMPONENT_TYPE
from zipline.components.aggregator import Aggregate
from collections import Counter
+3
View File
@@ -160,6 +160,9 @@ class TradeSimulationClient(Component):
def get_data(self):
for event in self.event_queue:
#alias the dt as datetime
event.datetime = event.dt
self.event_data[event['sid']] = event
self.event_queue = []
return self.event_data
+14 -7
View File
@@ -5,10 +5,17 @@ from zipline.transforms.base import BaseTransform
class MovingAverageTransform(BaseTransform):
def init(self, name, daycount=3):
self.daycount = daycount
def init(self, name, days=3):
self.state = {}
self.state['name'] = name
self.days = days
self.by_sid = defaultdict(self._create)
@property
def get_id(self):
return self.state['name']
def transform(self, event):
cur = self.by_sid[event.sid]
cur.update(event)
@@ -16,12 +23,12 @@ class MovingAverageTransform(BaseTransform):
return self.state
def _create(self):
return MovingAverage(self.daycount)
return MovingAverage(self.days)
class MovingAverage(object):
def init(self, daycount):
self.window = EventWindow(daycount)
def __init__(self, days):
self.window = EventWindow(days)
self.total = 0.0
self.average = 0.0
@@ -43,10 +50,10 @@ class EventWindow(object):
Tracks a window of the event history. Use an instance to track the events
inside your window to efficiently calculate rolling statistics.
"""
def init(self, daycount):
def __init__(self, days):
self.ticks = []
self.dropped_ticks = []
self.delta = timedelta(days=daycount)
self.delta = timedelta(days=days)
def update(self, event):
# add new event
+7 -1
View File
@@ -4,8 +4,15 @@ from zipline.transforms.base import BaseTransform
class ReturnsTransform(BaseTransform):
def init(self, name):
self.state = {}
self.state['name'] = name
self.by_sid = defaultdict(self._create)
@property
def get_id(self):
return self.state['name']
def transform(self, event):
cur = self.by_sid[event.sid]
cur.update(event)
@@ -27,7 +34,6 @@ class ReturnsFromPriorClose(object):
self.returns = 0.0
def update(self, event):
next_close = None
if self.last_close:
change = event.price - self.last_close.price
self.returns = change / self.last_close.price
+2 -2
View File
@@ -31,7 +31,7 @@ class TradeDataSource(DataSource):
def send(self, event):
"""
Sends the event iff it matches the internal SID filter.
Sends the event iff it matches the internal sid filter.
:param dict event: is a trade event with data as per
:py:func: `zipline.protocol.TRADE_FRAME`
:rtype: None
@@ -39,7 +39,7 @@ class TradeDataSource(DataSource):
event.source_id = self.source_id
if event.sid in self.filter['SID']:
if event.sid in self.filter['sid']:
message = zp.DATASOURCE_FRAME(event)
else:
blank = ndict({
+9 -3
View File
@@ -7,9 +7,15 @@ from zipline.finance.movingaverage import EventWindow
class VWAPTransform(BaseTransform):
def init(self, name, daycount=3):
self.state = {}
self.state['name'] = name
self.daycount = daycount
self.by_sid = defaultdict(self.create_vwap)
@property
def get_id(self):
return self.state['name']
def transform(self, event):
cur = self.by_sid[event.sid]
cur.update(event)
@@ -24,12 +30,12 @@ class DailyVWAP(object):
A class that tracks the volume weighted average price based on tick
updates.
"""
def init(self, name, daycount=3):
self.window = EventWindow(daycount)
def __init__(self, days=3):
self.window = EventWindow(days)
self.flux = 0.0
self.volume = 0
self.vwap = 0.0
self.delta = timedelta(days=daycount)
self.delta = timedelta(days=days)
def update(self, event):
+1 -1
View File
@@ -283,7 +283,7 @@ class SimulatedTrading(object):
"""
assert isinstance(source, DataSource)
self.check_started()
source.set_filter('SID', self.algorithm.get_sid_filter())
source.set_filter('sid', self.algorithm.get_sid_filter())
self.sim.register_components([source])
# ``id`` is name of source_id, ``get_id`` is the class name
+40 -41
View File
@@ -2,25 +2,25 @@
Algorithm Protocol
===================
For a class to be passed as a trading algorithm to the
For a class to be passed as a trading algorithm to the
:py:class:`zipline.lines.SimulatedTrading` zipline
it must follow an implementation protocol. Examples of this algorithm protocol
are provided below.
The algorithm must expose methods:
- initialize: method that takes no args, no returns. Simply called to
- initialize: method that takes no args, no returns. Simply called to
enable the algorithm to set any internal state needed.
- get_sid_filter: method that takes no args, and returns a list
of valid sids. List must have a length between 1 and 10. If None is returned
the filter will block all events.
- handle_data: method that accepts a :py:class:`zipline.protocol_utils.ndict`
- handle_data: method that accepts a :py:class:`zipline.protocol_utils.ndict`
of the current state of the simulation universe. An example data ndict::
+-----------------+--------------+----------------+--------------------+
| | SID(133) | SID(134) | SID(135) |
| | sid(133) | sid(134) | sid(135) |
+=================+==============+================+====================+
| price | $10.10 | $22.50 | $13.37 |
+-----------------+--------------+----------------+--------------------+
@@ -30,23 +30,22 @@ The algorithm must expose methods:
+-----------------+--------------+----------------+--------------------+
| dt | 6/30/2012 | 6/30/2011 | 6/29/2012 |
+-----------------+--------------+----------------+--------------------+
- set_order: method that accepts a callable. Will be set as the value of the
order method of trading_client. An algorithm can then place orders with a
valid SID and a number of shares::
self.order(SID(133), share_count)
- set_performance: property which can be set equal to the
cumulative_trading_performance property of the trading_client. An
- set_order: method that accepts a callable. Will be set as the value of the
order method of trading_client. An algorithm can then place orders with a
valid sid and a number of shares::
self.order(sid(133), share_count)
- set_performance: property which can be set equal to the
cumulative_trading_performance property of the trading_client. An
algorithm can then check position information with the
Portfolio object::
self.Portfolio[SID(133)]['cost_basis']
self.Portfolio[sid(133)]['cost_basis']
"""
import zipline.protocol as zp
class TestAlgorithm():
"""
@@ -54,7 +53,7 @@ class TestAlgorithm():
to verify the orders sent/received, transactions created, and positions
at the close of a simulation.
"""
def __init__(self, sid, amount, order_count):
self.count = order_count
self.sid = sid
@@ -64,26 +63,26 @@ class TestAlgorithm():
self.order = None
self.frame_count = 0
self.portfolio = None
def initialize(self):
pass
def set_order(self, order_callable):
self.order = order_callable
def set_portfolio(self, portfolio):
self.portfolio = portfolio
def handle_data(self, data):
self.frame_count += 1
#place an order for 100 shares of sid
if self.incr < self.count:
self.order(self.sid, self.amount)
self.incr += 1
def get_sid_filter(self):
return [self.sid]
return [self.sid]
#
class HeavyBuyAlgorithm():
"""
@@ -91,7 +90,7 @@ class HeavyBuyAlgorithm():
to verify the orders sent/received, transactions created, and positions
at the close of a simulation.
"""
def __init__(self, sid, amount):
self.sid = sid
self.amount = amount
@@ -100,41 +99,41 @@ class HeavyBuyAlgorithm():
self.order = None
self.frame_count = 0
self.portfolio = None
def initialize(self):
pass
pass
def set_order(self, order_callable):
self.order = order_callable
def set_portfolio(self, portfolio):
self.portfolio = portfolio
def handle_data(self, data):
self.frame_count += 1
#place an order for 100 shares of sid
self.order(self.sid, self.amount)
self.incr += 1
def get_sid_filter(self):
return [self.sid]
return [self.sid]
class NoopAlgorithm(object):
"""
Dolce fa niente.
"""
def initialize(self):
pass
def set_order(self, order_callable):
pass
def set_portfolio(self, portfolio):
pass
def handle_data(self, data):
pass
def get_sid_filter(self):
return None
return None
-1
View File
@@ -20,7 +20,6 @@ class BaseTransform(Component):
Parent class for feed transforms. Subclass and override transform
method to create a new derived value from the combined feed.
"""
def init(self):
pass
+2 -2
View File
@@ -57,13 +57,13 @@ def iso8061_to_epoch(datestring):
return EPOCH(dt)
def epoch_now():
dt = datetime.utcnow().replace(tzinfo=pytz.utc)
dt = utcnow()
return EPOCH(dt)
# UTC Datetime Subclasses
# -----------------------
def utcnow():
return datetime.now(pytz.utc)
return datetime.utcnow().replace(tzinfo=pytz.utc)
class utcdatetime(datetime):
def __new__(cls, *args, **kwargs):